POJ2762(Going from u to v or from v to u?)

题目链接

题目大意,给一个有向图,求是否任意两点都单向联通。

这题我用的是两次dfs求强连通图,将强连通分量缩成一个点,然后对缩点后的有向图进行拓扑排序,判断单项连通。因为一个小错误,WA了3次,第一次dfs时是求各点的后根遍历次序(时间戳),但是是以第cnt次访问的是第v个结点的形式来保存,这样可以很方便从访问次序找相应结点,便于第二次dfs。我在写的时候,不小心就写成了保存第v个结点的时间戳,自然就错了。

View Code
  1 #include <stdio.h>
2 #include <memory.h>
3 #define CLR(a) memset(a,0,sizeof(a))
4 #define N 1005
5 #define M 6005
6 struct node
7 {
8 int a,b;
9 } edge[M];
10 char g[N][N],vis[N];
11 int n,m,ord[N],id[N],topord[N],cnt;
12 void dfs(int u)
13 {
14 int v;
15 vis[u]=1;
16 for(v=1; v<=n; v++)
17 {
18 if(g[u][v]&&!vis[v])
19 {
20 dfs(v);
21 }
22 }
23 ord[cnt++]=u;
24 }
25 void rdfs(int u)
26 {
27 int v;
28 vis[u]=1;
29 id[u]=cnt;
30 for(v=1; v<=n; v++)
31 {
32 if(g[v][u]&&!vis[v])
33 {
34 rdfs(v);
35 }
36 }
37 }
38 void kosaraju()
39 {
40 int i,t,a,b;
41 CLR(vis);
42 for(i=1,cnt=1; i<=n; i++)
43 {
44 if(!vis[i]) dfs(i);
45 }
46 CLR(vis);
47 for(t=n,cnt=0; t>0; t--)
48 {
49 i=ord[t];
50 if(!vis[i])
51 {
52 cnt++;
53 rdfs(i);
54 }
55 }
56 CLR(g);
57 for(i=0; i<m; i++)
58 {
59 a=id[edge[i].a],b=id[edge[i].b];
60 if(a==b) continue;
61 g[a][b]=1;
62 }
63 }
64 void topsort()
65 {
66 int d[N],i,j,k;
67 for(i=1; i<=cnt; i++)
68 {
69 d[i]=0;
70 for(j=1; j<=cnt; j++)
71 {
72 if(i==j) continue;
73 d[i]+=g[j][i];
74 }
75 }
76 for(k=0; k<cnt; k++)
77 {
78 for(i=1; d[i]&&i<=n; i++);
79 d[i]=-1;
80 for(j=1; j<=cnt; j++) d[j]-=g[i][j];
81 topord[k]=i;
82 }
83 }
84 void judge()
85 {
86 int i,flag=1;
87 for(i=0; i<cnt-1; i++)
88 {
89 if(!g[topord[i]][topord[i+1]])
90 {
91 flag=0;
92 break;
93 }
94 }
95 if(flag) printf("Yes\n");
96 else printf("No\n");
97 }
98 int main()
99 {
100 int t,i,a,b;
101 scanf("%d",&t);
102 while(t--)
103 {
104 scanf("%d%d",&n,&m);
105 for(i=0; i<m; i++)
106 {
107 scanf("%d%d",&a,&b);
108 if(a==b) continue;
109 g[a][b]=1;
110 edge[i].a=a,edge[i].b=b;
111 }
112 kosaraju();
113 topsort();
114 judge();
115 CLR(g);
116 }
117 return 0;
118 }

 

posted @ 2012-03-31 22:38  BeatLJ  阅读(436)  评论(0编辑  收藏  举报