poj 2186 Popular Cows

http://poj.org/problem?id=2186   n头奶牛,给出若干个欢迎关系a b,表示a欢迎b,欢迎关系是单向的,但是是可以传递的。另外每个奶牛都是欢迎他自己的。
求出被所有的奶牛欢迎的奶牛的数目tarjan处理连通分量,每个连通分量缩点得到一个有向无环图DAG,若这个DAG只有一个点的出度为0,则该点代表的连通分量所含有的节点数,就是所求。

View Code
  1 #include<iostream>
2 #include<vector>
3 #include<cstring>
4 #include<cmath>
5 #include<stack>
6 using namespace std;
7 const int N=10008;
8 vector<int>mat[N];//原图
9 vector<int>mat2[N];//连通分量缩点后形成的图
10 int set[N];//连通分量
11 int num[N];//每个连通分量所含节点个数
12 int dfn[N];//访问编号
13 int low[N];
14 bool visited[N];//是否访问过
15 stack<int>stk;
16 bool instack[N];//是否在栈中
17 int n,m,cnt,seq;
18 void init()
19 {
20 int i;
21 for(i=0;i<=n;i++) mat[i].clear(),mat2[i].clear();
22 memset(visited,false,sizeof(visited));
23 memset(num,0,sizeof(num));
24 memset(instack,false,sizeof(instack));
25 while(!stk.empty()) stk.pop();
26 cnt=seq=0;
27 }
28 void tarjan(int cur)//求连通分量
29 {
30 dfn[cur]=low[cur]=++seq;
31 visited[cur]=true;
32 stk.push(cur);
33 instack[cur]=true;
34 int i;
35 for(i=0;i<mat[cur].size();i++)
36 {
37 int adj=mat[cur][i];
38 if(!visited[adj])
39 {
40 tarjan(adj);
41 low[cur]=min(low[cur],low[adj]);
42 }
43 else if(instack[adj]) low[cur]=min(low[cur],dfn[adj]);
44 }
45 if(dfn[cur]==low[cur])
46 {
47 cnt++;//连通分量个数++,从1开始
48 int temp;
49 while(true)
50 {
51 temp=stk.top();
52 stk.pop();
53 instack[temp]=false;
54 set[temp]=cnt;
55 num[cnt]++;//标记cnt这个连通分量有多少个节点
56 if(temp==cur) break;
57 }
58 }
59 }
60 void DAG()//缩点变为有向无环图
61 {
62 for(int i=1;i<=n;i++)
63 for(int j=0;j<mat[i].size();j++)
64 {
65 int adj=mat[i][j];
66 if(set[i] != set[adj]) mat2[set[i]].push_back(set[adj]);
67 }
68 }
69 void calc()//计算缩点后节点的初度,只有一个点的初度为0,该点所在的连通分量个数即为所求
70 {
71 int*out=new int[cnt+1];//存放出度
72 int i,j;
73 for(i=1;i<=cnt;i++)//出度
74 out[i]=mat2[i].size();
75 //for(i=1;i<=cnt;i++) cout<<"out["<<i<<"]:"<<out[i]<<endl;
76 int count=0,pos;
77 for(i=1;i<=cnt;i++)
78 if(out[i]==0) count++,pos=i;
79 if(count==1) cout<<num[pos]<<endl;
80 else cout<<"0"<<endl;
81 }
82 void print()
83 {
84 int i,j;
85 for(i=1;i<=n;i++) cout<<"set("<<i<<")="<<set[i]<<endl;
86 for(i=1;i<=cnt;i++) cout<<"num["<<i<<"]="<<num[i]<<endl;
87 for(i=1;i<=cnt;i++)
88 {
89 cout<<i<<":";
90 for(j=0;j<mat2[i].size();j++)
91 cout<<mat2[i][j]<<" ";
92 cout<<endl;
93 }
94 }
95 int main()
96 {
97 while(cin>>n>>m)
98 {
99 init();
100 int i,j,x,y;
101 for(i=0;i<m;i++)
102 {
103 cin>>x>>y;
104 mat[x].push_back(y);//输入矩阵
105 }
106 for(i=1;i<=n;i++)
107 if(!visited[i]) tarjan(i);
108 DAG();
109 //print();
110 calc();
111 }
112 return 0;
113 }


 

posted @ 2012-04-04 16:41  keepmoving89  阅读(143)  评论(0编辑  收藏  举报