1. 程式人生 > >資料結構課程設計-檢查網路(並查集)

資料結構課程設計-檢查網路(並查集)

檢查網路

給定一個計算機網路以及機器間的雙向連線列表,每一條連線與允許兩端的計算機進行直接的檔案傳輸,其他計算機間若存在一條連通路徑,也可以進行間接的檔案傳輸。

要求實現功能:

任意指定兩臺計算機,判斷整個網路中是否任意兩臺機器間都可以檔案傳輸?若不可以,請給出當前網路中連通分量的個數及各個連通分量中的機器。 增加兩臺計算機之間的連線。

基本要求:

至少使用兩種結構實現。

陣列實現:

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000
using namespace std;

int cc[maxn];  //用來記錄每個連通分量中的一個值,cc[1]=3:第一個連通分量中的一個值為3
int par[maxn],ran[maxn],a[maxn],b[maxn];

void Init(int n)  //初始化
{
    for(int i=0;i<=n;++i){
        par[i] = i;
        ran[i] = 0;
    }
}
int Find_par(int x)  //尋找父節點
{
    if(par[x]==x) return x;
    return par[x] = Find_par(par[x]);
}
void Unite(int x,int y)   //可連線的計算機了相連
{
    int fx = Find_par(x);
    int fy = Find_par(y);
    if(fx == fy) return ;
    if(ran[fx]<ran[fy])
        par[fx] = fy;
    else{
        par[fy] = fx;
        if(ran[fx]==ran[fy])
            ran[fx]++;
    }
}
int Acount(int n)  //計算連通分量個數
{
    int cnt=0,flag = 1,k;
    for(int i=1;i<=n;++i){
        if(Find_par(i)==i){
			cnt++;
			cc[cnt] = i;
		}
    }
    return cnt;
}
int main()
{
    int n,m,ans,mac1,mac2;
    char op;
    while(n|m){
        printf("請輸入計算機的數量:");
        scanf("%d",&n);
        printf("請輸入可直接相連的計算機的對數:");
        scanf("%d",&m);
        if(n>maxn||m>maxn){
            printf("\n資料越界,請重新輸入!!!\n\n\n");
            continue ;
        }
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        Init(n);
        printf("請輸入可直接相連的計算機機號:\n");
        for(int i=1;i<=m;++i){
            scanf("%d %d",&a[i],&b[i]);
            Unite(a[i],b[i]);
        }
        while(1){
            printf("請輸入想要的操作(Q:查詢連通情況,A:增加連線 ,N:退出):");
            cin>>op;
            if(op == 'Q'){  //查詢
                ans = Acount(n);
                if(ans == 1){
                    printf("任意兩臺計算機均可連通\n");
                }
                else{
                    printf("連通分量的個數為: %d\n",ans);
                    for(int i=1;i<=ans;i++){
                        printf("第%d個連通分量中的機器有 : ",i);
                        for(int j=1;j<=n;++j){
                            if(Find_par(cc[i])==Find_par(par[j]))
                                printf("%d ",j);
                        }
                        printf("\n");
                    }
                    printf("請輸入兩臺計算機序號,判斷其二者是都可以連通:(以0,0結束)\n");
                    while(scanf("%d %d",&mac1,&mac2)){
                        if(mac1+mac2==0) break;
                        if(Find_par(mac1) == Find_par(mac2)) printf("%d號計算機與%d號計算機可以連通\n",mac1,mac2);
                        else printf("二者無法連通\n");
                    }
                }
            }
            else if(op == 'A'){  //新增連線
                int num;
                printf("請輸入新增的連線數:\n");
                scanf("%d",&num);
                printf("請輸入新新增連線的機器號:\n");
                while(num--){
                    scanf("%d %d",&mac1,&mac2);
                    Unite(mac1,mac2);
                }
                continue;
            }
            else break;
        }
        printf("\n\n");
    }
    return 0;
}
/*
10 9

1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
輸出結果:
任意兩臺計算機均可連通

10 7

1 2
1 3
1 5
1 9
4 6
4 7
8 10

輸出結果:
連通分量的個數為: 3
第1個連通分量中的機器有 : 1 2 3 5 9
第2個連通分量中的機器有 : 4 6 7
第3個連通分量中的機器有 : 8 10

10 5

1 2
1 4
2 6
4 7
3 5

輸出結果:
連通分量的個數為: 5
第1個連通分量中的機器有 : 1 2 4 6 7
第2個連通分量中的機器有 : 3 5
第3個連通分量中的機器有 : 8
第4個連通分量中的機器有 : 9
第5個連通分量中的機器有 : 10

10 3

1 10
2 8
8 10
輸出結果:
連通分量的個數為: 7
第1個連通分量中的機器有 : 1 2 8 10
第2個連通分量中的機器有 : 3
第3個連通分量中的機器有 : 4
第4個連通分量中的機器有 : 5
第5個連通分量中的機器有 : 6
第6個連通分量中的機器有 : 7
第7個連通分量中的機器有 : 9


10 6

1 2
1 3
3 8
8 10
4 5
6 7
輸出結果:
連通分量的個數為: 4
第1個連通分量中的機器有 : 1 2 3 8 10
第2個連通分量中的機器有 : 4 5
第3個連通分量中的機器有 : 6 7
第4個連通分量中的機器有 : 9
*/

結構體實現:

#include <iostream>
#include <cstdio>
#define maxn 1000
using namespace std;


int cc[maxn]; //連通分量
struct node
{
	int data;
	int ran;
	int parent;
}t[maxn];

void Init(int n)
{
	for(int i=1;i<=n;++i)
	{
		t[i].data = i;
		t[i].ran = 0;
		t[i].parent = i;
	}
}
int Find_par(int x)
{
    if(t[x].parent==x) return x;
    return t[x].parent = Find_par(t[x].parent);
}
void Unite(int x,int y )
{
	x=Find_par(x);
	y=Find_par(y);
	if(x==y) return ;
	if( t[x].ran < t[y].ran )
		t[x].parent=y;
	else{
		t[y].parent=x;
		if( t[x].ran==t[y].ran)
			t[x].ran++;
	}
}
int Acount(int n)
{
    int cnt=0,flag = 1,k;
    for(int i=1;i<=n;++i){
        if(t[i].parent == i){
			cnt++;
			cc[cnt] = i;
		}
    }
    return cnt;
}
int main()
{
    int n,m,ans,mac1,mac2;
    char op;
    while(n|m){
        printf("請輸入計算機的數量:");
        scanf("%d",&n);
        printf("請輸入可直接相連的計算機的對數:");
        scanf("%d",&m);
        if(n>maxn||m>maxn){
            printf("\n資料越界,請重新輸入!!!\n\n\n");
            continue ;
        }
        Init(n);
        printf("請輸入可直接相連的計算機機號:\n");
        for(int i=1;i<=m;++i){
            scanf("%d %d",&mac1,&mac2);
            Unite(mac1,mac2);
        }
       while(1){
            printf("請輸入想要的操作(Q:查詢連通情況,A:增加連線 ,N:退出):");
            cin>>op;
            if(op == 'Q'){  //查詢
                ans = Acount(n);
                if(ans == 1){
                    printf("任意兩臺計算機均可連通\n");
                }
                else{
                    printf("連通分量的個數為: %d\n",ans);
                    for(int i=1;i<=ans;i++){
                        printf("第%d個連通分量中的機器有 : ",i);
                        for(int j=1;j<=n;++j){
                            if(Find_par(cc[i])==Find_par(t[j].parent))
                                printf("%d ",j);
                        }
                        printf("\n");
                    }
                    printf("請輸入兩臺計算機序號,判斷其二者是都可以連通:(以0,0結束)\n");
                    while(scanf("%d %d",&mac1,&mac2)){
                        if(mac1+mac2==0) break;
                        if(Find_par(mac1) == Find_par(mac2)) printf("%d號計算機與%d號計算機可以連通\n",mac1,mac2);
                        else printf("二者無法連通\n");
                    }
                }
            }
            else if(op == 'A'){  //新增連線
                int num;
                printf("請輸入新增的連線數:\n");
                scanf("%d",&num);
                printf("請輸入新新增連線的機器號:\n");
                while(num--){
                    scanf("%d %d",&mac1,&mac2);
                    Unite(mac1,mac2);
                }
                continue;
            }
            else break;
        }
        printf("\n\n");
    }
    return 0;
}