数据结构实验:连通分量个数
題目描述
?在無(wú)向圖中,如果從頂點(diǎn)vi到頂點(diǎn)vj有路徑,則稱vi和vj連通。如果圖中任意兩個(gè)頂點(diǎn)之間都連通,則稱該圖為連通圖, 否則,稱該圖為非連通圖,則其中的極大連通子圖稱為連通分量,這里所謂的極大是指子圖中包含的頂點(diǎn)個(gè)數(shù)極大。 例如:一個(gè)無(wú)向圖有5個(gè)頂點(diǎn),1-3-5是連通的,2是連通的,4是連通的,則這個(gè)無(wú)向圖有3個(gè)連通分量。 ?輸入
?第一行是一個(gè)整數(shù)T,表示有T組測(cè)試樣例(0 < T <= 50)。每個(gè)測(cè)試樣例開(kāi)始一行包括兩個(gè)整數(shù)N,M,(0 < N <= 20,0 <= M <= 200) 分別代表N個(gè)頂點(diǎn),和M條邊。下面的M行,每行有兩個(gè)整數(shù)u,v,頂點(diǎn)u和頂點(diǎn)v相連。輸出
?每行一個(gè)整數(shù),連通分量個(gè)數(shù)。示例輸入
2 3 1 1 2 3 2 3 2 1 2示例輸出
2 1提示
#include <iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
typedef struct arcnode
{
? ? int adj;
}arcnode,adjmatrix[200][200];
typedef struct
{
? ? adjmatrix a;
? ? int vn;
? ? int an;
}MG;
int create(MG &g,int n,int m)//生成鄰接矩陣;
{
? ? int i,j;
? ? int v1,v2;
? ? g.vn=n;
? ? g.an=m;
? ? for(i=1;i<=g.vn;i++)
? ? ? ? for(j=1;j<=g.vn;j++)
? ? ? ? ?g.a[i][j].adj=0;
? ? for(i=1;i<=g.an;i++)
? ? {
? ? ? ? scanf("%d%d",&v1,&v2);
? ? ? ? g.a[v1][v2].adj=1;
? ? ? ? g.a[v2][v1]=g.a[v1][v2];
? ? }
? ? return 1;
}
int v[110];//標(biāo)記圖的頂點(diǎn)是否訪問(wèn)過(guò);
void dfs(MG &g,int i)//深度優(yōu)先搜索;
{
? ? int j;//j在函數(shù)內(nèi)部,不然不能回溯;
? ? v[i]=1;
? ? for(j=1;j<=g.vn;j++)
? ? ? ? if(g.a[i][j].adj==1&&!v[j])
? ? {
? ? ? ? dfs(g,j);
? ? }
}
int i,count;//記錄連通分量個(gè)數(shù);
void dfs1(MG &g)//統(tǒng)計(jì)連通分量的個(gè)數(shù)
{
? ? //int i;//若不在函數(shù)內(nèi)部不會(huì)回溯;
? ? for(i=1;i<=g.vn;i++)
? ? ? ? if(!v[i])
? ? {
? ? ? ? count++;
? ? ? ? dfs(g,i);
? ? }
}
int main()
{
? ? int t;
? ? MG g;
? ? scanf("%d",&t);
? ? while(t--)
? ? {
? ? ? ? count=0;
? ? ? ? memset(v,0,sizeof(v));//標(biāo)記數(shù)組初始化;
? ? ? ? int n,m;
? ? ? ? scanf("%d%d",&n,&m);
? ? ? ? create(g,n,m);
? ? ? ? dfs1(g);
? ? ? ? printf("%d\n",count);
? ? }
? ? return 0;
}
#include <cstdio> #define MAX 2000 using namespace std;int pre[MAX+1];void Initialize(int n) { // 初始化各結(jié)點(diǎn)的 pre 為自身for(int i=0; i<=n; ++i) { // 相當(dāng)于初始時(shí)每個(gè)結(jié)點(diǎn)為各自獨(dú)立的集合pre[i] = i;} }int Find(int a) { // 查找 a 所在集合的根結(jié)點(diǎn) rootint root = a; // root 初始化為其本身while(pre[root] != root) { // 當(dāng) root 的上級(jí)結(jié)點(diǎn)不是其本身root = pre[root]; // 令 root 為它的上級(jí)結(jié)點(diǎn),繼續(xù)查找}while(pre[a] != root) { // 再次遍歷,路徑壓縮int temp = pre[a];pre[a] = root; // 沿途結(jié)點(diǎn)直接指向到 roota = temp;}return root; }void Join(int a, int b) { // 將 a, b 結(jié)點(diǎn)所在的集合合并int root_a = Find(a); // 查找 a 所在集合的根結(jié)點(diǎn)int root_b = Find(b); // 查找 b 所在集合的根結(jié)點(diǎn)if(root_a != root_b) { // 如果 a, b 不在同一集合,則合并if(root_a > root_b) // 根結(jié)點(diǎn)下標(biāo)大的集合并入下標(biāo)小的集合pre[root_a] = root_b;else pre[root_b] = root_a;} }int Count(int n) { // 統(tǒng)計(jì)不相交集合的個(gè)數(shù)int cnt = 0; // 計(jì)數(shù)變量for(int i=1; i<=n; ++i) {int root = Find(i); // 找到一個(gè)集合if(root) { // 如果是第一次找到此集合cnt++; // 計(jì)數(shù)pre[root] = 0; // 此根節(jié)點(diǎn)置0,防止重復(fù)}}return cnt; }int main(int argc, char const *argv[]) {int t, n, m, u, v;scanf("%d", &t);while(t--) {scanf("%d %d", &n, &m);Initialize(n);while(m--) {scanf("%d %d", &u, &v);Join(u, v);}printf("%d\n", Count(n));}return 0; }
總結(jié)
以上是生活随笔為你收集整理的数据结构实验:连通分量个数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: mongodb最详细的安装与配置
- 下一篇: 数据结构实验之栈六:下一较大值(二)