求无向图连通子图个数
测试数据由m+1行构成,第一行为两个正整数n(1<n<=30),m(1<m<100),顶点数,边数
m行数据是边的信息,表示该边关联的两个顶点
输出两行信息,第一行连通子图个数,第二行按照升序输出每个连通子图中顶点个数
输入样例
9 8
1 2
1 3
2 4
3 4
5 7
5 6
6 7
8 9
输出样例
3
2 3 4
#include<stdio.h>
#define MAX 35
int Matrix[MAX][MAX];
int vset[MAX] = {0};
int vex[MAX];
int sum, n, m;
int dfs (int x);
int main (void) {
int i, j, count = 0, u, v, w = 0, t;
scanf ("%d %d", &n, &m);
while (m--) {
scanf ("%d %d", &u, &v);
Matrix[u][v] = 1;
Matrix[v][u] = 1;
}
/*for (i = 1; i <= n; i++) {
for (j = 1; j<= n; j++) {
printf ("%d ", Matrix[i][j]);
}
printf ("\n");
}*/
/*for (i = 1; i <= n; i++) {
printf ("%d",vset[i]);
}*/
for (i = 1; i <= n; i++) {
if (vset[i] == 0) {
dfs (i);
count++;
}
}
printf ("%d\n", count);
for (i = 1; i <= n; i++) {
vset[i] = 0;
}
/*for (i = 1; i <= n; i++) {
printf ("%d",vset[i]);
}*/
for (i = 1; i <= n; i++) {
if (vset[i] == 0) {
sum = 1;
dfs (i);
vex[w] = sum;
w++;
//printf ("%d", sum);
}
}
for (i = 0; i < w; i++) {
for (j = 0; j < w - 1 - i; j++) {
if (vex[j] > vex[j + 1]) {
t = vex[j];
vex[j] = vex[j + 1];
vex[j + 1] = t;
}
}
}
for (i = 0; i < w; i++) {
printf ("%d ", vex[i]);
}
return 0;
}
int dfs (int x) {
vset[x] = 1;
int i;
for (i = 1; i <= n; i++) {
if (vset[i] == 0 && Matrix[i][x] == 1) {
sum++;
dfs (i);
}
}
}
C++可以看这位,连通子图。
每日一感慨C++确实方便hhh,尤其是STL的使用。换到C里要多很多代码。
关于深度优先搜索DFS可以看下《算法笔记》,个人感觉还是挺好理解的。当然理解是一回事,能够代码实现又是一回事,还是要自己多练。
利用这道题记录一下我个人比较欠缺的点吧
1.DFS的代码实现
在不看ppt不看笔记的情况下单对着编辑器敲出来还是有点困难,总是漏掉这个或者那个。最近ddl太多,肝完再来填这个坑吧。
2.全局变量的使用
在知道全局变量占用空间比较大的时候,下意识的就想不到用全局变量,导致很多时候在函数间传递数值的时候,还要思考怎么传,用指针或者多添加一个形参,在DFS这种递归的条件下,多一个指针也好,多一个参数也好,都很占用空间,还不如一个全局变量,上一个函数修改完,下一个函数能够直接使用这个数值。在当前这个数据量的情况下,全局变量也占用不了太多空间。
3.数组下标的使用
利用数组下标标记是否访问过该元素。(当元素内容是abc时,可利用a-'a’将其转化为数字来标记。