图的遍历——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",¤tPoint); 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",¤tPoint); 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; }