图的遍历——A1013Battle over cities(25) 求需要添加多少条边才能构成连通图转化为找连通分量(可由DFS 和 并查集来找连通分量)

#include <bits/stdc++.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;
const int N = 1111;
vector<int> G[N];//邻接表
bool vis[N];//标记顶点i是否被访问
int currentPoint;//当前需要删除的顶点编号
void dfs(int v){
    if(v == currentPoint) return;
    vis[v] = true;
    for(int i = 0;i<G[v].size();++i){
        if(vis[G[v][i]] == false){
            dfs(G[v][i]);
        }
    }

}

int n,m,k;
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;++i){
        int a,b;
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    for(int query = 0;query < k;++query){
        scanf("%d",&currentPoint);
        memset(vis,false,sizeof(vis));//初始化vis数组为false
        int block = 0;//联通块个数,初始化为0
        for(int i=1;i<=n;++i){
            if(i != currentPoint && vis[i] == false){//如果未被删除且未被访问
                dfs(i);
                block++;
            }
        }
        printf("%d\n",block - 1);//输出联通块个数-1,表示需要增加的边

    }
    system("pause");
    return 0;
}

并查集

#include <bits/stdc++.h>
#include <stdio.h>
#include <stdlib.h>
#include <queue>
using namespace std;
const int N = 1111;
vector<int> G[N];//邻接表
int father[N];
bool vis[N];
int findFather(int x){
    int a = x;
    while(x != father[x]){
        x = father[x];
    }
    //路径压缩,为了避免超时
    while(a != father[a]){
        int z = a;
        a = father[a];
        father[z] = x;
    }
    return x;
}
void Union(int a,int b){
    int faA = findFather(a);
    int faB = findFather(b);
    if(faA != faB){
        father[faA] = faB;
    }
}
void init(){
    for(int i = 1;i<N;++i){
        father[i] = i;
        vis[i] = false;
    }
}
int n,m,k;
int main(){
    scanf("%d%d%d",&n,&m,&k);
    for(int i=0;i<m;++i){
        int a,b;
        scanf("%d%d",&a,&b);
        G[a].push_back(b);
        G[b].push_back(a);
    }
    int currentPoint;
    for(int query = 0;query < k;++query){
        scanf("%d",&currentPoint);
        init();
        for(int i=1;i<=n;++i){
            for(int j= 0;j<G[i].size();++j){
                int u = i,v = G[i][j];//边的两个端点
                if(u == currentPoint || v == currentPoint) continue;
                Union(u,v);
            }
        }
        int block = 0;//联通块个数
        for(int i = 1;i<=n;++i){
            if(i == currentPoint){
                continue;
            }
            int fa_i = findFather(i);
            if(vis[fa_i] == false){
                block++;
                vis[fa_i] = true;
            }
        }
        printf("%d\n",block - 1);
    }
    system("pause");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/JasonPeng1/p/12294033.html
今日推荐