• bzoj 1093 最大半连通子图


    一个有向图G=(V,E)称为半连通的(Semi-Connected),如果满足:?u,v∈V,满足u→v或v→u,即对于图中任意两点u,v,存在一条u到v的有向路径或者从v到u的有向路径。若G'=(V',E')满足V'?V,E'是E中所有跟V'有关的边,则称G'是G的一个导出子图。若G'是G的导出子图,且G'半连通,则称G'为G的半连通子图。若G'是G所有半连通子图中包含节点数最多的,则称G'是G的最大半连通子图。给定一个有向图G,请求出G的最大半连通子图拥有的节点数K,以及不同的最大半连通子图的数目C。由于C可能比较大,仅要求输出C对X的余数。

    Input

      第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8

    Output

      应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

    Sample Input

    6 6 20070603
    1 2
    2 1
    1 3
    2 4
    5 6
    6 4

    Sample Output

    3
    3

      题目大意 一个有向图G(V, U)是半连通的,当且仅当任意点,并且存在一条路径,它上面的所有边属于U,并且从u到v或者从v到u。图G的导出子图G‘(V'. U'),满足.一个有向图G的半连通子图是一个导出子图且半连通,最大半连通子图是其中拥有最多点数的半连通子图。问最大的半连通子图的点数和数量。

      因为半连通子图一定是导出子图,所以两个半连通子图是否同构之和它们的定点集合有关。

      由于图上可能有环(强连通分量),所以考虑缩点。缩点后的图是个DAG,然后你可得到一个结论就是这个DAG上的一条路径就是原图的一个半连通子图,并且DAG上的路径和原图中的半连通子图一一对应。

      我们可以赋予每个点一个点权,代表它在原图中代表的点数。

      于是这个问题转换成在DAG上最长路及其计数。这个拓扑排序再加个小dp就可以水过了。

      另外注意拓扑排序的时判断重边。

    Code

      1 /**
      2  * bzoj
      3  * Problem#1093
      4  * Accepted
      5  * Time: 1988ms
      6  * Memory: 13740k
      7  */
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 #define smin(a, b) a = min(a, b)
     12 #define smax(a, b) b = max(a, b)
     13 
     14 int n, m;
     15 int moder;
     16 vector<int> *g;
     17 
     18 inline void init() {
     19     scanf("%d%d%d", &n, &m, &moder);
     20     g = new vector<int>[(n + 1)];
     21     for(int i = 1, u, v; i <= m; i++) {
     22         scanf("%d%d", &u, &v);
     23         g[u].push_back(v); 
     24     }
     25 }
     26 
     27 int cnt = 0;
     28 stack<int> s;
     29 int* visitID;
     30 int* exitID;
     31 int* belong;
     32 boolean *visited;
     33 boolean *instack;
     34 inline void init_tarjan() {
     35     visitID = new int[(n + 1)];
     36     exitID = new int[(n + 1)];
     37     visited = new boolean[(n + 1)];
     38     instack = new boolean[(n + 1)];
     39     belong = new int[(n + 1)];
     40     memset(visited, false, sizeof(boolean) * (n + 1));
     41     memset(instack, false, sizeof(boolean) * (n + 1));
     42 }
     43 
     44 void tarjan(int node) {
     45     visitID[node] = exitID[node] = ++cnt;
     46     visited[node] = instack[node] = true;
     47     s.push(node);
     48     
     49     for(int i = 0; i < (signed)g[node].size(); i++) {
     50         int& e = g[node][i];
     51         if(!visited[e]) {
     52             tarjan(e);
     53             smin(exitID[node], exitID[e]);
     54         } else if(instack[e]) {
     55             smin(exitID[node], visitID[e]);
     56         }
     57     }
     58     
     59     if(visitID[node] == exitID[node]) {
     60         int e;
     61         do {
     62             e = s.top();
     63             s.pop();
     64             instack[e] = false;
     65             belong[e] = node;
     66         } while(e != node);
     67     }
     68 }
     69 
     70 vector<int> *ng;
     71 int* dag;
     72 int *val;
     73 inline void rebuild() {
     74     dag = new int[(n + 1)];
     75     ng = new vector<int>[(n + 1)];
     76     val = new int[(n + 1)];
     77     memset(val, 0, sizeof(int) * (n + 1));
     78     memset(dag, 0, sizeof(int) * (n + 1));
     79 
     80     for(int i = 1; i <= n; i++)
     81         for(int j = 0; j < (signed)g[i].size(); j++) {
     82             int& e = g[i][j];
     83             if(belong[e] != belong[i])
     84                 ng[belong[i]].push_back(belong[e]), dag[belong[e]]++;
     85         }
     86         
     87     for(int i = 1; i <= n; i++)
     88         val[belong[i]]++;
     89 }
     90 
     91 queue<int> que;
     92 int *dis;
     93 int *counter;
     94 inline void topu() {
     95     dis = new int[(n + 1)];
     96     counter = new int[(n + 1)];
     97     memset(dis, 0, sizeof(int) * (n + 1));
     98     memset(visited, false, sizeof(boolean) * (n + 1));
     99     
    100     for(int i = 1; i <= n; i++)
    101         if(belong[i] == i && !dag[i])
    102             que.push(i), dis[i] = val[i], counter[i] = 1;
    103             
    104     while(!que.empty()) {
    105         int e = que.front();
    106         que.pop();
    107         for(int i = 0; i < (signed)ng[e].size(); i++) {
    108             int& eu = ng[e][i];
    109             dag[eu]--;
    110             if(!dag[eu])
    111                 que.push(eu);
    112             if(visited[eu])    continue;
    113             visited[eu] = true;
    114             
    115             if(dis[e] + val[eu] > dis[eu]) {
    116                 dis[eu] = dis[e] + val[eu];
    117                 counter[eu] = counter[e];
    118             } else if(dis[e] + val[eu] == dis[eu])
    119                 counter[eu] = (counter[eu] + counter[e]) % moder;
    120         }
    121         for(int i = 0; i < (signed)ng[e].size(); i++)
    122             visited[ng[e][i]] = false;
    123     }
    124 }
    125 
    126 int maxdis = -1, res = 0;
    127 inline void solve() {
    128     for(int i = 1; i <= n; i++) {
    129         if(belong[i] != i)    continue;
    130         if(dis[i] > maxdis)    {
    131             maxdis = dis[i];
    132             res = counter[i];
    133         } else if(dis[i] == maxdis)
    134             (res += counter[i]) %= moder;
    135     }
    136     printf("%d
    %d", maxdis, res);
    137 }
    138 
    139 int main() {
    140     init();
    141     init_tarjan();
    142     for(int i = 1; i <= n; i++)
    143         if(!visited[i])
    144             tarjan(i);
    145     rebuild();
    146     topu();
    147     solve();
    148     return 0;
    149 }
  • 相关阅读:
    entityframework学习笔记--002-database first
    ServletContext总结
    form 表单提交类型
    对称加密与非对称加密
    跨域详解
    https工作原理
    Entity Framework数据库初始化四种策略
    Modbus 协议解析
    CAFFE(FAQ.2):Ubuntu 配置caffe 框架之数据库读取,错误解决:ImportError: No module named leveldb解决办法
    CAFFE(0):Ubuntu 下安装anaconda2和anaconda3
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7326267.html
Copyright © 2020-2023  润新知