LA4287图论+ 有向图SCC+缩点

 1 /*
 2 LA4287图论
 3 有向图SCC
 4 关键点:
 5 1、事件抽象成图的节点
 6 2、建立相似的模型(有向图SCC)
 7 3、等效代替:缩点的思想
 8 4、图论知识:非强连通转强连通

     补充:a个缩点入度为0b个出度为0,则添加max(a,b)条有向边,可以成为有向图的强连通分量

 9 */
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <math.h>
14 #include <ctype.h>
15 #include <string>
16 #include <iostream>
17 #include <sstream>
18 #include <vector>
19 #include <queue>
20 #include <stack>
21 #include <map>
22 #include <list>
23 #include <set>
24 #include <algorithm>
25 #define maxn 20100
26 using namespace std;
27 
28 int pre[maxn] , low[maxn] , sccno[maxn] , dfs_clock , scc_cnt;
29 vector<int>G[maxn];
30 stack<int>S;
31 
32 void dfs(int u){
33     pre[u] = low[u] = ++dfs_clock;
34     S.push(u);
35     int ecnt = G[u].size();
36     for(int i=0;i<ecnt;i++){
37         int v = G[u][i];
38         if(!pre[v]){
39             dfs(v);
40             low[u] = min(low[u] , low[v]);
41         }
42         else if(!sccno[v]){
43             low[u] = min(low[u] , pre[v]);
44         }
45     }
46     if(low[u] == pre[u]){
47         scc_cnt++;
48         for(;;){
49             int x = S.top() ; S.pop();
50             sccno[x] = scc_cnt;
51             if(x==u) break;
52         }
53     }
54 }
55 void find_scc(int n){
56     dfs_clock = scc_cnt = 0;
57     memset(pre, 0 ,sizeof(pre));
58     memset(sccno , 0, sizeof(sccno));
59     for(int i=1;i<=n; i++){
60         if(!pre[i]) dfs(i);
61     }
62 }
63 int solve(int n)
64 {
65     find_scc(n);
66     bool ind[maxn],oud[maxn];//缩点后的顶点的入度,出度是否大于0
67     memset(ind,0,sizeof(ind));
68     memset(oud,0,sizeof(oud));
69     for(int i=1;i<=n;i++){//枚举每条边
70     for(int j=0;j<G[i].size();j++){
71     int u=i,v=G[i][j];
72     if(sccno[u]!=sccno[v]) oud[sccno[u]]=ind[sccno[v]]=true;
73     }
74     }
75     int a=0,b=0;
76     for(int i=1;i<=scc_cnt;i++){
77     if(!ind[i]) a++;
78     if(!oud[i]) b++;
79     }
80     if (scc_cnt==1) return 0;else return max(a,b);
81     //ps,scc_cnt==1时错误产生原因:上面的方法是运用必要条件来判断,破坏入度/出度为0的唯一情况,但是如果只有一个连通块,初始值就出现问题了
82 }
83 int main()
84 {
85     int n,m;
86     int t;cin>>t;
87     while(t--){
88         cin>>n>>m;
89         for(int i=1;i<=n;i++) G[i].clear();
90         for(int i=1;i<=m;i++){
91         int u,v;
92         cin>>u>>v;
93         G[u].push_back(v);
94         }
95         cout<<solve(n)<<endl;
96     }
97     return 0;
98 }

 

posted @ 2014-02-26 21:04  little_w  阅读(662)  评论(0编辑  收藏  举报