pku 2762 Going from u to v or from v to u?

强联通+拓扑排序判断~~

题目大意:给定一个有向图,问该图是不是半连通图.

所谓半连通图即是指 在连通图中任意给出两个点a,b,要保证至少存在一条从a到b,或者从b到a的边。

解题思路:先用强联通进行缩点,之后再重新建图,再用拓扑排序进行判断:当某一时刻存在两个或两个以上入度为0的点则输出No,否则输出Yes!

为了学习双联通不得不学习了tarjan,先用tarjan把这个题给A了。之后不太过瘾,又用Kosaraju给A了下,结果发现Kosaraju要比tarjan更快。。很神奇。。

可能是因为我写的tarjan太丑陋了!! 或者是我写的Kosaraju更风骚一点。。 ^_^。。 不过我感觉还是后者比较容易理解一点,我写的也比较清晰!!

分别贴下两种方法的代码:

tarjan:

 

View Code
  1 # include<stdio.h>
2 # include<string.h>
3 # include<stack>
4 using namespace std;
5 # define N 1005
6 # define M 6005
7 struct node{
8 int from,to,next;
9 }edge[M],edge1[M];
10 int tol,head[N],visit[N],dfn[N],low[N],n,m,vis[N],cnt,flag,Belong[N],count,degree[N],tol1,head1[N];
11 //int adj[N][N];
12 stack<int>S;
13 void add(int a,int b)
14 {
15 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
16 }
17 void add1(int a,int b)
18 {
19 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
20 }
21 int min(int a,int b)
22 {
23 return a<b?a:b;
24 }
25 void tarjan(int u)
26 {
27 int j,v;
28 dfn[u]=low[u]=cnt++;
29 visit[u]=vis[u]=1;
30 S.push(u);
31 for(j=head[u];j!=-1;j=edge[j].next)
32 {
33 v=edge[j].to;
34 if(!visit[v])
35 {
36 tarjan(v);
37 low[u]=min(low[u],low[v]);
38 }
39 else if(vis[v]) low[u]=min(low[u],dfn[v]);
40 }
41 if(low[u]==dfn[u])
42 {
43 count++;
44 do{
45 v=S.top();
46 S.pop();
47 vis[v]=0;
48 Belong[v]=count;
49 }while(v!=u);
50 }
51 }
52 int main()
53 {
54 int i,ncase,count1,index,a,b,index1,j;
55 scanf("%d",&ncase);
56 while(ncase--)
57 {
58 scanf("%d%d",&n,&m);
59 memset(head,-1,sizeof(head));
60 tol=0;
61 for(i=1;i<=m;i++)
62 {
63 scanf("%d%d",&a,&b);
64 add(a,b);
65 }
66 memset(visit,0,sizeof(visit));
67 memset(vis,0,sizeof(vis));
68 cnt=0;
69 count=0;
70 for(i=1;i<=n;i++)
71 if(!visit[i]) tarjan(i);
72 // memset(adj,0,sizeof(adj));
73 memset(degree,0,sizeof(degree));
74 tol1=0;
75 memset(head1,-1,sizeof(head1));
76 for(i=0;i<tol;i++)
77 {
78 a=edge[i].from;
79 b=edge[i].to;
80 if(Belong[a]!=Belong[b])
81 {
82 //if(!adj[Belong[a]][Belong[b]])
83 //{
84 // adj[Belong[a]][Belong[b]]=1;
85 add1(Belong[a],Belong[b]);
86 degree[Belong[b]]++;
87 //}
88 }
89 }
90 count1=0;
91 for(i=1;i<=count;i++)
92 {
93 if(degree[i]==0) {count1++;index=i;}
94 }
95 if(count1!=1) {printf("No\n");continue;}
96 flag=0;
97 while(1)
98 {
99 count1=0;
100 /*for(i=1;i<=count;i++)
101 {
102 if(adj[index][i])
103 {
104 degree[i]--;
105 if(degree[i]==0)
106 {
107 count1++;
108 index1=i;
109 }
110 }
111 }*/
112 for(j=head1[index];j!=-1;j=edge1[j].next)
113 {
114 i=edge1[j].to;
115 degree[i]--;
116 if(degree[i]==0)
117 {
118 count1++;
119 index1=i;
120 }
121 }
122 if(count1>1) {flag=1;break;}
123 else if(count1==0) break;
124 index=index1;
125 }
126 if(flag) printf("No\n");
127 else printf("Yes\n");
128 }
129 return 0;
130 }

Kosaraju:

View Code
  1 # include<stdio.h>
2 # include<string.h>
3 # define N 1005
4 # define M 6005
5 struct node{
6 int from,to,next;
7 }edge1[M],edge2[M],edge[M];
8 int head1[N],visit1[N],visit2[N],head2[N],T[N],Belong[N],head[N],degree[N];
9 int tol1,tol2,tol,Tcnt,Bcnt,n,m;
10 void add1(int a,int b)
11 {
12 edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;
13 edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++;
14 }
15 void add(int a,int b)
16 {
17 edge[tol].from=a;edge[tol].to=b;edge[tol].next=head[a];head[a]=tol++;
18 }
19 void dfs1(int i)
20 {
21 int j,u;
22 visit1[i]=1;
23 for(j=head1[i];j!=-1;j=edge1[j].next)
24 {
25 u=edge1[j].to;
26 if(!visit1[u]) dfs1(u);
27 }
28 T[Tcnt++]=i;
29 }
30 void dfs2(int i)
31 {
32 int j,u;
33 visit2[i]=1;
34 Belong[i]=Bcnt;
35 for(j=head2[i];j!=-1;j=edge2[j].next)
36 {
37 u=edge2[j].to;
38 if(!visit2[u]) dfs2(u);
39 }
40 }
41 int main()
42 {
43 int i,j,ncase,count,index,a,b;
44 scanf("%d",&ncase);
45 while(ncase--)
46 {
47 scanf("%d%d",&n,&m);
48 tol1=tol2=0;
49 Bcnt=Tcnt=0;
50 memset(head1,-1,sizeof(head1));
51 memset(head2,-1,sizeof(head2));
52 memset(visit1,0,sizeof(visit1));
53 memset(visit2,0,sizeof(visit2));
54 for(i=1;i<=m;i++)
55 {
56 scanf("%d%d",&a,&b);
57 add1(a,b);
58 }
59 for(i=1;i<=n;i++)
60 if(!visit1[i]) dfs1(i);
61 for(i=Tcnt-1;i>=0;i--)
62 {
63 if(!visit2[T[i]])
64 {
65 dfs2(T[i]);
66 Bcnt++;
67 }
68 }
69 memset(head,-1,sizeof(head));
70 memset(degree,0,sizeof(degree));
71 tol=0;
72 for(i=0;i<tol1;i++)
73 {
74 a=edge1[i].from;
75 b=edge1[i].to;
76 if(Belong[a]!=Belong[b])
77 {
78 add(Belong[a],Belong[b]);
79 degree[Belong[b]]++;
80 }
81 }
82 count=0;
83 for(i=0;i<Bcnt;i++)
84 {
85 if(degree[i]==0)
86 {
87 count++;
88 index=i;
89 }
90 }
91 if(count>1) {printf("No\n");continue;}
92 while(1)
93 {
94 count=0;
95 for(j=head[index];j!=-1;j=edge[j].next)
96 {
97 i=edge[j].to;
98 degree[i]--;
99 if(degree[i]==0)
100 {
101 count++;
102 index=i;
103 }
104 }
105 if(count>1) {printf("No\n");break;}
106 else if(count==0) {printf("Yes\n");break;}
107 }
108 }
109 return 0;
110 }

你可能感兴趣的:(pku)