圖的深度遍歷(C語言)鄰接矩陣表示

愛吃土豆的小菜狗發表於2022-02-25

 

知識講解:

圖的遍歷分為兩種,深度遍歷與廣度遍歷。這裡討論深度遍歷。

以上圖為例討論圖(圖片來自《演算法筆記》)的深度遍歷:

設圖形的頂點數為n。

先從頂點v0開始,用一個陣列vis[n]來表示該頂點是否被訪問,如果未被訪問,vis[頂點編號]=0,否則為1.從v0開始訪問,則vis[0]=1,v0可以連通v1與v2,即下一個訪問的頂點是v1(遍歷二維陣列時1比2先訪問到),再更新vis陣列,然後再從v1訪問v3,到v3時發現沒有辦法繼續訪問了,再退回上一個頂點v1(v1仍存在未被訪問的岔道),從v1訪問沒有被訪問過的v4,再從v4出發訪問v5,到v5時無法再訪問其餘的頂點,回退至上一個存在未被訪問岔道的頂點v0,訪問未被訪問的v2,至此所有頂點均被訪問,遍歷結束。

遍歷要用遞迴實現;

程式碼實現:

 

int vis[1005],n;

int a[1005][1005];

void DFS(int v){

vis[v]=1;//該頂點被訪問

for(int i=1;i<=n;i++)

     {

if(a[v][i]==1&&vis[i]==0)//與之有連線的點是否被訪問過

{

DFS(i);

         }

     }

}

void DFSG()

{

for(int i=0;i<n;i++){

if(vis[i]==0){

DFS(i);}

}

}

 

 

 

例題研究:

1013 Battle Over Cities (25 分)

It is vitally important to have all the cities connected by highways in a war. If a city is occupied by the enemy, all the highways from/toward that city are closed. We must know immediately if we need to repair any other highways to keep the rest of the cities connected. Given the map of cities which have all the remaining highways marked, you are supposed to tell the number of highways need to be repaired, quickly.

Input Specification:

Each input file contains one test case. Each case starts with a line containing 3 numbers N (<1000), M and K, which are the total number of cities, the number of remaining highways, and the number of cities to be checked, respectively. Then M lines follow, each describes a highway by 2 integers, which are the numbers of the cities the highway connects. The cities are numbered from 1 to N. Finally there is a line containing K numbers, which represent the cities we concern.

Output Specification:

For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.

Sample Input:
3 2 3
1 2
1 3
1 2 3

 

Sample Output:
1
0
0

 

來源網站:https://pintia.cn/problem-sets/994805342720868352/problems/994805500414115840

思路分析:

這道題的題意是,一個圖如果刪除一個頂點,新增幾條邊能保證其他點的聯通。

先介紹概念連通體:連通體就是一個最大連通的子圖(可以是一個點,兩個相連的點)。

根據題意,我們需要討論圖要形成連通圖的條件:假如某個圖有n個連通體,v0,v1……vn,如果它們要連通,至少需要n-1條邊相連,這裡特別注意將整個連通體視作一個整體,也可以將其視為一整個頂點。

這道題可以先通過深度遍歷找到連通體(深度遍歷是在不斷形成最大連通體),判斷連通體的數量(即每次遍歷到底後又回到有未訪問岔口的頂點的時候計數器+1);需要新增的邊就是連通體數量-1.這裡需特別注意,刪除一個點不能在圖上真的刪除它,只能在遍歷到被刪除的點時就返回。

程式碼實現:

#include <stdio.h>
#include <string.h>
int vis[1005],n,m,k,delet;
int a[1005][1005];
void DFS(int v){
    if(v==delet) return;
    vis[v]=1;
     for(int i=1;i<=n;i++)
     {
         if(a[v][i]==1&&vis[i]==0){
             DFS(i);
         }
     }
}
int main()
{
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            a[i][j]=-1;
            a[j][i]=-1;
        }
    }
    for(int i=0;i<m;i++){
        int x,y;
        scanf("%d %d",&x,&y);
        a[x][y]=1;
        a[y][x]=1;
    }
    while(k--){
       
        scanf("%d",&delet);
        int block=0;
        //vis[delet]=1;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=n;i++){
        if(vis[i]==0&&i!=delet){
            DFS(i);
            block++;
        }
    }
    printf("%d\n",block-1);
    }
    return 0;
}

 

 

  

 

 

 

相關文章