wenbao与tarjan

 

Tarjan

求强联通图,割点,桥相关问题

 

用vis[i]标记i点第几次被访问,low数组标记i点能够到达的最远的祖先,那么当low·[i] == vis[i] 构成联通图。。。low[i] >= vis[i]时为割点(关节点)

 

 1 struct Node{
 2     int from, to, next;
 3 }v[maxn];
 4 void add(int from, int to){
 5     v[e].from = from;
 6     v[e].to = to;
 7     v[e].next = head[from];
 8     head[from] = e++;
 9 }
10 int vis[maxn], l[maxn], s[maxn];
11 void t(int x, int num){
12     vis[x] = 1;
13     l[x] = num;
14     s[++top] = x;
15     for(int i = head[x]; i != -1; i = v[i].next){
16         int xx = v[i].to;
17         if(!vis[xx]) t(xx, num+1);
18         if(vis[xx] == 1) l[x] = min(l[xx], l[x]); 
19     }
20     if(l[x] == num){
21         do{
22             vis[s[top]] = -1;
23         }while(s[top--] != x);
24     }
25 }

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=1269

乱入。。。。。。。。。。

这个题并查集什么的随便搞搞就可以了吧,全当练手

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 const int maxn = 1e5+10;
 5 int n, m, e, sum;
 6 int head[maxn];
 7 bool vis[maxn];
 8 struct Node{
 9     int to, next;
10 }v[maxn];
11 void add(int from, int to){
12     v[e].to = to;
13     v[e].next = head[from];
14     head[from] = e++;
15 }
16 int l[maxn];
17 void t(int x, int num){
18     vis[x] = true;
19     l[x] = num;
20     for(int i = head[x]; i != -1; i = v[i].next){
21         int xx = v[i].to;
22         if(!vis[xx]) t(xx, num+1);
23         l[x] = min(l[xx], l[x]);
24     }
25     if(l[x] == num) sum++;
26 }
27 int main(){
28     while(~scanf("%d%d", &n, &m) && (n+m)){
29         memset(head, -1, sizeof(int)*maxn);
30         e = 0, sum = 0;
31         memset(vis, false, sizeof(bool)*maxn);
32         int x, y;
33         for(int i = 0; i < m; ++i){
34             scanf("%d%d", &x, &y);
35             add(x, y);
36         }
37         for(int i = 1; i <= n; ++i){
38             if(!vis[i]) t(i, 0);
39         }
40         printf("%s\n", sum == 1 ? "Yes" : "No");
41     }
42     return 0;
43 }

 

 

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=1827

中文题

 

jarjan将强联通图缩为一点

 

 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 const int maxn = 2e3+10;
 6 int n, m, e, top, num2;
 7 int a[maxn], b[maxn], head[maxn], d[maxn], f[maxn];
 8 struct Node{
 9     int from, to, next;
10 }v[maxn];
11 void add(int from, int to){
12     v[e].from = from;
13     v[e].to = to;
14     v[e].next = head[from];
15     head[from] = e++;
16 }
17 int vis[maxn], l[maxn], s[maxn];
18 void t(int x, int num){
19     vis[x] = 1;
20     l[x] = num;
21     s[++top] = x;
22     for(int i = head[x]; i != -1; i = v[i].next){
23         int xx = v[i].to;
24         if(!vis[xx]) t(xx, num+1);
25         if(vis[xx] == 1) l[x] = min(l[xx], l[x]); 
26     }
27     if(l[x] == num){
28         int mi = 1e9;
29         do{
30             d[s[top]] = num2;
31             mi = min(mi, a[s[top]]);
32             vis[s[top]] = -1;
33         }while(s[top--] != x);
34         b[num2++] = mi;
35     }
36 }
37 int main(){
38     while(~scanf("%d%d", &n, &m)){
39         for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
40         memset(head, -1, sizeof(int)*maxn);
41         memset(f, 0, sizeof(int)*maxn);
42         e = 0, top = 0;
43         int x, y, sum = 0, cnt = 0;
44         for(int i = 0; i < m; ++i){
45             scanf("%d%d", &x, &y);
46             add(x, y);
47         }
48         num2 = 0;
49         memset(vis, 0, sizeof(int)*maxn);
50         for(int i = 1; i <= n; ++i){
51             if(!vis[i]) t(i, 0);
52         }
53         for(int i = 0; i < e; ++i){
54             int xx = v[i].from, yy = v[i].to;
55             if(d[xx] != d[yy]) f[d[yy]]++;
56         }
57         for(int i = 0; i < num2; ++i){
58             if(!f[i]) cnt ++, sum += b[i];
59         }
60        printf("%d %d\n", cnt, sum);
61     }
62     return 0;
63 }

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

http://acm.hdu.edu.cn/showproblem.php?pid=2767

 

给定有向图,求最少添加多少条边变为强连通图

 

tarjan缩点,转化为DAG(DAG变为连通图,max(入度为零,出度为零), 注意特殊情况)

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 const int maxn = 50009;
 5 struct Node{
 6     int from, to, next;
 7 }v[maxn];
 8 int e;
 9 int head[maxn], f[maxn], w[maxn];
10 void add(int from, int to){
11     v[e].from = from;
12     v[e].to = to;
13     v[e].next = head[from];
14     head[from] = e++;
15 }
16 int s[maxn], num2, d[maxn], top, l[maxn];
17 void q(int x, int num){
18     s[++top] = x;
19     l[x] = num;
20     for(int i = head[x]; i != -1; i = v[i].next){
21         int xx = v[i].to;
22         if(l[xx] == -1) q(xx, num+1);
23         if(l[xx] >= 0) l[x] = min(l[x], l[xx]);
24     }
25     if(l[x] == num){
26         do{
27             l[s[top]] = -2;
28             d[s[top]] = num2;
29         }while(s[top--] != x);
30         num2 ++;
31     }
32 }
33 int main(){
34     int t, n, m;
35     scanf("%d", &t);
36     while(t--){
37         scanf("%d%d", &n, &m);
38         memset(head, -1, sizeof(int)*maxn);
39         e = 0, top = 0;
40         int x, y;
41         for(int i = 0; i < m; ++i){
42             scanf("%d%d", &x, &y);
43             add(x, y);
44         }
45         memset(l, -1, sizeof(int)*maxn);
46         num2 = 0;
47         for(int i = 1; i <= n; ++i){
48             if(l[i] == -1) q(i, 0);
49         }
50         memset(f, 0, sizeof(int)*maxn);
51         memset(w, 0, sizeof(int)*maxn);
52         for(int i = 0; i < e; ++i){
53             int xx = v[i].from, yy = v[i].to;
54             if(d[xx] != d[yy]){
55                 f[d[xx]] ++, w[d[yy]] ++;
56             }
57         }
58         int sum1 = 0, sum2 = 0;
59         for(int i = 0; i < num2; ++i){
60             if(!f[i]) sum1 ++;
61             if(!w[i]) sum2 ++;
62         }
63         sum1 = max(sum1, sum2);
64         printf("%d\n", sum1 == 1 ? 0 : sum1);
65     }
66     return 0;
67 }

 

 

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

http://poj.org/problem?id=1523 

 

求无向图的割点,,

一样的套路

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 const int maxn = 2e3+10;
 5 struct Node{
 6     int from, to, next;
 7 }v[maxn];
 8 int e, head[maxn];
 9 void add(int from, int to){
10     v[e].from = from;
11     v[e].to = to;
12     v[e].next = head[from];
13     head[from] = e ++;
14 }
15 int l[maxn], b[maxn];
16 void d(int x, int num){
17     l[x] = num;
18     int mi = 1e9;
19     for(int i = head[x]; i != -1; i = v[i].next){
20         int xx = v[i].to;
21         if(l[xx] == -1){ 
22             d(xx, num+1);
23             if(l[xx] >= num){
24                 //cout<<xx<<" "<<x<<" "<<l[xx]<<endl;
25                 b[x] ++;
26             }
27         }
28         mi = min(mi, l[xx]);
29     }
30     l[x] = mi;
31     if(num == 0) b[x] --;
32 }
33 int main(){
34     int x, y, t = 1, ma;
35     while(~scanf("%d", &x) && x){
36         memset(head, -1, sizeof(int)*maxn);
37         e = 0;
38         scanf("%d", &y);
39         add(x, y), add(y, x);
40         while(~scanf("%d", &x) && x){
41             scanf("%d", &y);
42             add(x, y), add(y, x);
43         }
44         memset(l, -1, sizeof(int)*maxn);
45         memset(b, 0, sizeof(int)*maxn);
46         d(y, 0);
47         bool flag = false;
48         printf("Network #%d\n", t++);
49         for(int i = 1; i <= 1000; ++i){
50             if(b[i]){
51                 printf("  SPF node %d leaves %d subnets\n", i, b[i]+1);
52                 flag = true;
53             }
54         }
55         if(!flag) printf("  No SPF nodes\n");
56         printf("\n");
57     }
58     return 0;
59 }

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

http://poj.org/problem?id=1144

 

求割点

 

 1 #include <iostream>
 2 #include <string.h>
 3 using namespace std;
 4 const int maxn = 2e4+10;
 5 struct Node{
 6     int from, to, next;
 7 }v[maxn];
 8 int head[maxn], e;
 9 void add(int from, int to){
10     v[e].from = from;
11     v[e].to = to;
12     v[e].next = head[from];
13     head[from] = e++;
14 }
15 int l[maxn], sum;
16 void d(int x, int num){
17     l[x] = num;
18     int mi = 1e9, num2 = 0;
19     for(int i = head[x]; i != -1; i = v[i].next){
20         int xx = v[i].to;
21         if(l[xx] == -1){
22             d(xx, num+1);
23             if(l[xx] >= num) num2 ++;
24         }
25         mi = min(mi, l[xx]);
26     }
27     l[x] = mi;
28     if(num == 0) num2 --;
29     if(num2) sum ++;
30 }
31 int main(){
32     int n, x, y;
33     while(~scanf("%d", &n) && n){
34         memset(head, -1, sizeof(int)*maxn);
35         e = 0, sum = 0;
36         while(~scanf("%d", &x) && x){
37             while(getchar() != '\n'){
38                 scanf("%d", &y);
39                 add(x, y), add(y, x);
40             }
41         }
42         memset(l, -1, sizeof(int)*maxn);
43         d(1, 0);
44         printf("%d\n", sum);
45     }
46     return 0;
47 }

 

 

 

 

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

只有不断学习才能进步!

 

posted @ 2018-04-14 13:55  wenbao  阅读(120)  评论(0编辑  收藏  举报