[51nod] 1076 2条不相交的路径 #边双联通分量

1076 2条不相交的路径

基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 
给出一个无向图G的顶点V和边E。进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径。(两条路径不经过相同的边)
(注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路)
 
Input
第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量。(2 <= M <= 25000, 1 <= N <= 50000)
第2 - N + 1行,每行2个数,中间用空格分隔,分别是N条边的起点和终点的编号。例如2 4表示起点为2,终点为4,由于是无向图,所以从4到2也是可行的路径。
第N + 2行,一个数Q,表示后面将进行Q次查询。(1 <= Q <= 50000)
第N + 3 - N + 2 + Q行,每行2个数s, t,中间用空格分隔,表示查询的起点和终点。
Output
共Q行,如果从s到t存在2条不相交的路径则输出Yes,否则输出No。
Input示例
4 4
1 2
2 3
1 3
1 4
5
1 2
2 3
3 1
2 4
1 4
Output示例
Yes
Yes
Yes
No
No
Analysis
第一次知道原来边双联通分量的求法和强联通分量求法几乎一样...
只不过在无向图中的边双就没有 “在栈中” 的概念了,而是要保证不会走到自己父亲那里
= = 模拟一下发现确实两种要求的tarjan代码是一模一样的
= =
 
Code
 1 #include<stdio.h>
 2 #include<iostream>
 3 #define maxn 1000000
 4 using namespace std;
 5 
 6 int dfn[maxn],low[maxn],TIM,COL,color[maxn],n,m,q;
 7 bool iscut[2*maxn],buck[maxn*2];
 8 
 9 struct edge{ int from,u,v,bri; }e[maxn*2];
10 int tot,first[maxn]; void insert(int u,int v){
11     tot++; e[tot].bri = 0; e[tot].u = u; e[tot].from = first[u]; e[tot].v = v; first[u] = tot;
12 }
13 
14 void dfs(int u,int fa){ // To tag the bri
15     dfn[u] = low[u] = ++TIM;
16     int child = 0;
17     for(int i = first[u];i;i = e[i].from){
18         int v = e[i].v; //if(v == fa) continue;
19         if(v != fa) child++;
20         if(!dfn[v]){
21             dfs(v,u);
22             low[u] = min(low[u],low[v]);
23             if(low[v] >= dfn[u]) iscut[u] = true;
24         }else if(dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]);
25     }if(fa == u && child > 1) iscut[u] = false;
26 //    printf("#%d: child %d iscut %d\n",u,child,iscut[u]);
27 }
28 
29 void tagg(){
30     for(int i = 1;i <= tot;i++)
31         if(iscut[e[i].u] && iscut[e[i].v])
32             e[i].bri = 1, buck[i] = true;
33 }
34 
35 void dfs1(int u,int fa){
36     color[u] = COL;
37     for(int i = first[u];i;i = e[i].from){
38         if(e[i].v == fa || buck[i] || color[e[i].v]) continue;
39         dfs1(e[i].v,u);
40     }
41 }
42 
43 int main(){
44 //    freopen("16.txt","r",stdin);
45 //    freopen("16.out","w",stdout);
46     
47     scanf("%d%d",&n,&m);
48     
49     for(int i = 1;i <= m;i++){
50         int u,v; scanf("%d%d",&u,&v);
51         insert(u,v); insert(v,u);
52     }for(int i=1;i<=n;i++)if(!dfn[i])
53     dfs(i,i); for(int i = 1;i <= n;i++)
54         if(!e[first[i]].from) iscut[i] = true;
55 //    for(int i = 1;i <= n;i++) printf("%d ",iscut[i]); cout << endl;
56     tagg(); 
57     
58 //    for(int i = 1;i <= tot;i++) printf("#%d:%d->%d $%d$\n",i,e[i].u,e[i].v,buck[i]);
59 //    for(int i = 1;i <= n;i++) printf("%d ",color[i]); cout << endl;
60     
61     for(int i = 1;i <= n;i++)
62         if(!color[i]){ ++COL; dfs1(i,i); }
63     
64     scanf("%d",&q);
65     
66     for(int i = 1;i <= q;i++){
67         int u,v; scanf("%d%d",&u,&v);
68         if(color[u] == color[v]) printf("Yes\n");
69         else printf("No\n");
70     }
71     
72     return 0;
73 }
判桥 -> 边双联通
 1 #include<stdio.h>
 2 #include<iostream>
 3 #define maxn 2000000
 4 using namespace std;
 5 
 6 int dfn[maxn],low[maxn],TIM,s[maxn],poi,color[maxn],COL,n,m,q;
 7 
 8 struct edge{ int from, u, v; }e[maxn];
 9 int tot,first[maxn]; void insert(int u,int v){
10     tot++; e[tot].from = first[u]; e[tot].v = v; e[tot].u = u; first[u] = tot;
11 }
12 
13 void dfs(int u,int fa){
14 //    printf("Now deep in #%d\n",u);
15     dfn[u] = low[u] = ++TIM;
16     s[poi++] = u;
17     for(int i = first[u];i;i = e[i].from){
18         int v = e[i].v; if(!dfn[v]){
19 //            printf("#%d; get in Poi B\n",u);
20             dfs(v,u); low[u] = min(low[u],low[v]);
21         }else if(dfn[v] < dfn[u] && v != fa) low[u] = min(low[u],dfn[v]);
22     }//printf("#%d: get in poi A\n",u);
23     
24     if(low[u] == dfn[u]){
25 //        printf("#%d get the first!\n",u);
26         color[u] = ++COL;
27         while(s[poi-1] != u && poi){
28             poi--; color[s[poi]] = COL;
29         }if(poi) poi--;
30     }
31 }
32 
33 int main(){
34     scanf("%d%d",&n,&m);
35     
36     for(int i = 1;i <= m;i++){
37         int u,v; scanf("%d%d",&u,&v);
38         insert(u,v); insert(v,u);
39     }for(int i = 1;i <= n;i++)
40         if(!color[i]) dfs(i,i);
41     
42 //    for(int i = 1;i <= n;i++) printf("%d ",color[i]); cout << endl;
43     
44     scanf("%d",&q);
45     
46     for(int i = 1;i <= q;i++){
47         int u,v; scanf("%d%d",&u,&v);
48         if(color[u] == color[v]) printf("Yes\n");
49         else printf("No\n");
50     }
51     
52     
53     
54     
55     return 0;
56 }
Tarjan强联通分量

 

posted @ 2017-11-08 16:48  μSsia  阅读(284)  评论(0编辑  收藏  举报