九度oj 题目1109:连通图

题目描述:

    给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。

输入:

    每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。如果 n 为 0 表示输入结束。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。

输出:

    对于每组输入数据,如果所有顶点都是连通的,输出"YES",否则输出"NO"。

样例输入:
4 3
1 2
2 3
3 2
3 2
1 2
2 3
0 0
样例输出:
NO
YES

这个题一开始用深度优先搜索做的,代码如下
 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 
 5 int map[1002][1002];
 6 int flag[1002];
 7 int n, m;
 8 
 9 void dfs(int k) {
10     flag[k] = 1;
11     for(int i = 1; i <= n; i++) {
12         if(flag[i] == 0 && map[k][i] == 1) {
13             dfs(i);
14         }
15     } 
16 }
17 
18 int main(int argc, char const *argv[])
19 {
20     //freopen("input.txt","r",stdin);
21     while(scanf("%d %d",&n,&m) != EOF && n != 0) {
22         memset(map,0, sizeof(map));
23         memset(flag, 0, sizeof(flag));
24 
25         while(m--) {
26             int a, b;
27             scanf("%d %d",&a, &b);
28             map[a][b] = map[b][a] = 1;
29         }
30         flag[1] = 1;
31         dfs(1);
32         bool isOk = true;
33         for(int i = 1; i <=n; i++) {
34             if(flag[i] == 0) {
35                 isOk = false;
36                 break;
37             }
38         }
39         if(isOk) {
40             puts("YES");
41         }
42         else {
43             puts("NO");
44         }
45 
46     }    
47     return 0;
48 }

但耗时略长,内存占用略大

后来试了试迪杰特斯拉算法的变形

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 
 5 int map[1002][1002];
 6 int flag[1002];
 7 int n, m;
 8 
 9 void dfs(int k) {
10     flag[k] = 1;
11     for(int i = 1; i <= n; i++) {
12         if(flag[i] == 0 && map[k][i] == 1) {
13             dfs(i);
14         }
15     } 
16 }
17 
18 int main(int argc, char const *argv[])
19 {
20     freopen("input.txt","r",stdin);
21     while(scanf("%d %d",&n,&m) != EOF && n != 0) {
22         memset(map,0, sizeof(map));
23         memset(flag, 0, sizeof(flag));
24 
25         while(m--) {
26             int a, b;
27             scanf("%d %d",&a, &b);
28             map[a][b] = map[b][a] = 1;
29         }
30         flag[1] = 1;
31         
32         for(int i = 2; i <= n; i++) {
33             for(int j = 1; j <= n; j++) {
34                 if(flag[j] == 0 && map[1][j] == 1) {
35                     flag[j] = 1;
36                     for(int k = 1; k <= n; k++) {
37                         if(map[j][k] == 1) {
38                             map[1][k] = 1;
39                         }
40                     }
41                 }
42             }
43         }
44 
45         bool isOk = true;
46         for(int i = 1; i <=n; i++) {
47             if(flag[i] == 0) {
48                 isOk = false;
49                 break;
50             }
51         }
52         if(isOk) {
53             puts("YES");
54         }
55         else {
56             puts("NO");
57         }
58 
59     }    
60     return 0;
61 }

但耗时更长

也试了试flyod算法

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 
 5 int map[1002][1002];
 6 int n, m;
 7 
 8 int main(int argc, char const *argv[])
 9 {
10     //freopen("input.txt","r",stdin);
11     while(scanf("%d %d",&n,&m) != EOF && n != 0) {
12         memset(map,0, sizeof(map));
13 
14         while(m--) {
15             int a, b;
16             scanf("%d %d",&a, &b);
17             map[a][b] = map[b][a] = 1;
18         }
19         map[1][1] = 1;
20         for(int i = 1; i <= n; i++) {
21             for(int j = 1; j <= n; j++) {
22                 for(int k = 1; k <= n; k++) {
23                     if(map[j][i] == 1 && map[i][k] == 1) {
24                         map[j][k] = 1;
25                     }
26                 }
27             }
28         }
29 
30 
31         bool isOk = true;
32         for(int i = 1; i <=n; i++) {
33             if(map[1][i] == 0) {
34                 isOk = false;
35                 break;
36             }
37         }
38         if(isOk) {
39             puts("YES");
40         }
41         else {
42             puts("NO");
43         }
44 
45     }    
46     return 0;
47 }

直接超时了

突然会想起一个月前做的题,好像叫做并查集的东西,代码如下

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <cstring>
 4 
 5 int next[1002];
 6 int n, m;
 7 
 8 int find(int t) {
 9     while(next[t] != 0) {
10         t = next[t];
11     }
12     return t;
13 }
14 
15 int main(int argc, char const *argv[])
16 {
17     //freopen("input.txt","r",stdin);
18     while(scanf("%d %d",&n,&m) != EOF && n != 0) {
19         memset(next, 0, sizeof(next));
20 
21         while(m--) {
22             int a, b;
23             scanf("%d %d",&a, &b);
24             int fa = find(a);
25             int fb = find(b);
26             if(fa != fb) {
27                 next[fa] = b; 
28             }
29         }
30         
31         int isOk = 0;
32         for(int i = 1; i <= n; i++) {
33             if(next[i] == 0) {
34                 isOk++;
35                 if(isOk >= 2) {
36                     puts("NO");
37                     break;
38                 }
39             }
40         }
41         if(isOk == 1) {
42             puts("YES");
43         }
44 
45     }    
46     return 0;
47 }

耗时和内存都有质的飞跃,但如何再进一步优化呢?

posted @ 2016-08-16 19:47  Jason杰  阅读(333)  评论(0编辑  收藏  举报