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.
For each of the K cities, output in a line the number of highways need to be repaired if that city is lost.
3 2 3<br/>1 2<br/>1 3<br/>1 2 3
1<br/>0<br/>0
package go.jacob.day830; import java.util.Scanner; /** * 1013. Battle Over Cities (25) * * @author Jacob 运用连通集。 * 连通集具体数据结构参考:http://blog.csdn.net/zjkc050818/article/details/77703880 * 这里使用quick_union */ public class Demo2 { static int count;// 记录连通集个数 private static int[] id;// 记录每个节点属于哪个集合 private static int[] size;// 记录每个集合的节点个数,当将两个集合连通时,将节点数较少的集合加到节点数较多的集合上 public static void main(String[] args) { Scanner sc = new Scanner(System.in); int citys = sc.nextInt(), roads = sc.nextInt(), checked = sc.nextInt(); if(citys<2){ System.out.println(0); return; } // 由于节点序号是从1开始,所以初始化的时候要注意 id = new int[citys + 1]; size = new int[citys + 1]; // 保存所有路径 int[][] road = new int[roads][2]; for (int i = 0; i < roads; i++) { road[i][0] = sc.nextInt(); road[i][1] = sc.nextInt(); } int[] checkCity = new int[checked]; for (int i = 0; i < checked; i++) checkCity[i] = sc.nextInt(); for (int i = 0; i < checked; i++) { init(); solve(checkCity[i], road); } sc.close(); } // 初始化id和size数组.每个节点属于本节点,且个数为1 private static void init() { for (int i = 1; i < id.length; i++) { id[i] = i; size[i] = 1; } count = id.length-1; } private static void solve(int root, int[][] road) { for (int i = 0; i < road.length; i++) { int p = road[i][0], q = road[i][1]; // 如果本条路径中有root节点,则跳过此次循环。 if (p == root || q == root) continue; union(p,q); } //count()返回连通集个数,-2的原因是: //删除某一个节点需要减1,删除以后,如果有N个连通集,相连需要N-1条边 System.out.println(count()-2); } /* * 查找p属于的连通集 */ private static int find(int p) { while(id[p]!=p) p=id[p]; return p; } /* * 将p,q所在的两个连通集相连 */ private static void union(int p, int q) { int pRoot=find(p),qRoot=find(q); if(pRoot==qRoot) return; if(size[pRoot]>size[qRoot]){ id[qRoot]=pRoot; size[pRoot]+=size[qRoot]; }else{ id[pRoot]=qRoot; size[qRoot]+=size[pRoot]; } count--; } /* * 返回连通集数 */ private static int count() { return count; } }
//Dfs实现联通块的计算 #include <cstdio> #include <cstring> #include <vector> using namespace std; const int maxn = 1000 + 10; int current_point, vis[maxn]; vector<int> G[maxn]; void dfs(int p){ if(p == current_point) return; if(vis[p]) return; vis[p] = 1; for(unsigned int i=0;i<G[p].size();i++){ dfs(G[p][i]); } } int main(){ int n, m, k; scanf("%d %d %d", &n, &m, &k); for(int i=0;i<m;i++){ int p1, p2; scanf("%d %d", &p1, &p2); G[p1].push_back(p2); G[p2].push_back(p1); } for(int i=0;i<k;i++){ int block=0; scanf("%d", ¤t_point); memset(vis, 0, sizeof(vis)); for(int j=1;j<=n;j++){ if(!vis[j]){ dfs(j); block ++; } } printf("%d\n", block-2); } if(n && !m && k) printf("0\n"); return 0; }
//并查集实现较为简单且高效 #include <set> #include <vector> #include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn = 1000 + 10; struct Edge { int p1, p2; Edge(int u, int v):p1(u), p2(v) {} }; set<int> block; vector<Edge> edges; int p[maxn]; int find_sym(int x){ return (p[x] == x)? x : (p[x] = find_sym(p[x])); } int main(){ int n, m, k; scanf("%d %d %d", &n, &m, &k); for(int i=0;i<m;i++){ int u, v; scanf("%d %d", &u, &v); edges.push_back(Edge(u, v)); } for(int i=0;i<k;i++){ int lost_city; scanf("%d", &lost_city); block.clear(); memset(p, 0, sizeof(p)); for(int j=1;j<=n;j++) p[j] = j; for(int h=0;h<m;h++){ Edge e = edges[h]; if(e.p1==lost_city || e.p2==lost_city) continue; else{ int x = find_sym(e.p1); int y = find_sym(e.p2); if(x!=y) p[x] = y; } } for(int j=1;j<=n;j++){ int symbol = find_sym(j); if(!block.count(symbol)) block.insert(symbol); } cout << block.size()-2 << endl; } return 0; }
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=1010;
int n,m,k,ans,v1,v2;
int G[maxn][maxn];
bool vis[maxn]={false};
void DFS(int u){
vis[u]=true;
for(int v=1;v<=n;v++){
if(vis[v]==false&&G[u][v]==1)
DFS(v);
}
}
void DFSTrave(){
for(int u=1;u<=n;u++){
if(vis[u]==false){
DFS(u);
ans++;
}
}
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
scanf("%d%d",&v1,&v2);
G[v1][v2]=G[v2][v1]=1;
}
for(int i=1;i<=k;i++){
fill(vis,vis+1010,false); //初始化访问结点
cin>>v1;
vis[v1]=true; //本轮绕过v1
ans=0;
DFSTrave();
if(n==1) cout<<0<<"\n"; //特例,只有一个点时
else cout<<ans-1<<"\n"; //要添加的边数即为连通分量数减1
}
return 0;
}
#include<iostream>
#include<string>
#include<vector>
using namespace std;
struct Edge
{
int nextIndex;//下一个结点的id
bool isUsed;//是否损毁
};
void dfs(vector<Edge> roadMaps[1001],int N,int nextRoadId,bool *usedCity)
{
usedCity[nextRoadId] = true;
for(int i=0;i<roadMaps[nextRoadId].size();i++)
{
int nextId = roadMaps[nextRoadId][i].nextIndex;
if(!usedCity[nextId]&&roadMaps[nextRoadId][i].isUsed)
dfs(roadMaps,N,nextId,usedCity);
}
};
void checkThisNode(vector<Edge> roadMaps[1001],int checkCityId,int N)
{
int realId = checkCityId-1;
//cout<<"check:"<<checkCityId<<endl;
for(int i=0;i<roadMaps[realId].size();i++)
{
roadMaps[realId][i].isUsed = false;//设置成被损毁的路
}
bool usedCity[1001]={false};
//找到孤立的结点,然后遍历
int sum = 0;
for(int i=0;i<N;i++)
{
if(i==realId)
continue;
if(!usedCity[i])
sum++;
dfs(roadMaps,N,i,usedCity);
}
cout<<sum-1<<endl;
for(int i=0;i<roadMaps[realId].size();i++)
{
roadMaps[realId][i].isUsed = true;//恢复被损毁的路
}
};
int main()
{
int N,M,K;
scanf("%d %d %d",&N,&M,&K);
vector<Edge> roadMaps[1001];
for(int i=0;i<M;i++)
{
int a,b;
scanf("%d %d",&a,&b);
Edge tmp;
tmp.nextIndex = b-1;
tmp.isUsed = true;
roadMaps[a-1].push_back(tmp);
Edge tmp2;
tmp2.nextIndex = a-1;
tmp2.isUsed = true;
roadMaps[b-1].push_back(tmp2);
//cout<<"a="<<a<<" b="<<b<<endl;
}
//cout<<"id:"<<roadMaps[0][2].nextIndex<<endl;
for(int i=0;i<K;i++)
{
int needCheck;
scanf("%d",&needCheck);
checkThisNode(roadMaps,needCheck,N);
}
return 0;
}
#include<bits/stdc++.h> using namespace std; const int Max=1010; vector<int> G[Max]; bool visit[Max]; int query; void DFS(int v) { visit[v]=1; for(int i=0; i<G[v].size(); i++) { if(!visit[G[v][i]]&&G[v][i]!=query) { DFS(G[v][i]); } } } int main() { int n,m,k; scanf("%d %d %d",&n,&m,&k); for(int i=0; i<m; i++) { int x,y; scanf("%d %d",&x,&y); G[x].emplace_back(y); G[y].emplace_back(x); } for(int q=0; q<k; q++) { scanf("%d",&query); int answer=-1; memset(visit,0,sizeof(visit)); for(int i=1; i<=n; i++) { if(query==i||visit[i]) continue; DFS(i); answer++; } if(answer==-1) printf("0"); else printf("%d\n",answer); } return 0; }
#include<cstdio> (802)#include<algorithm> using namespace std; const int maxn=1010; const int INF=0x3fffffff; int G[maxn][maxn]={0},graph[maxn][maxn]; bool vis[maxn]; void DFS(int start,int n) { vis[start]=true; for(int i=1;i<=n;i++) { if(vis[i]==false&&graph[start][i]==1) DFS(i,n); } } int main() { int n,m,k; scanf("%d%d%d",&n,&m,&k); if(n==1) { puts("0"); return 0; } for(int i=0;i<m;i++) { int c1,c2; scanf("%d%d",&c1,&c2); G[c1][c2]=1; G[c2][c1]=1; } for(int i=0;i<k;i++) { fill(vis,vis+maxn,false); int c=0,num=0; for(int j=1;j<=n;j++) for(int m=1;m<=n;m++) graph[j][m]=G[j][m]; scanf("%d",&c); for(int j=1;j<=n;j++) if(graph[c][j]==1) { graph[c][j]=0; graph[j][c]=0; } for(int j=1;j<=n;j++) if(vis[j]==false) { num++; DFS(j,n); } printf("%d\n",num-2); } return 0; }
#include<bits/stdc++.h> using namespace std; int G[1005][1005] ={0}; int vis[1005]; void dfs(int i ,int n) { vis[i] = 1; for (int j = 1; j < n+1; j++) { if (vis[j] == 0 && G[i][j] == 1) { dfs(j, n); } } } int main() { int n, m, k; cin >> n >> m >> k; while (m--) { int a, b; scanf("%d %d",&a,&b); G[a][b] = 1; G[b][a] = 1; } int city; while (cin >> city) { fill(vis,vis+1005,0); vis[city] = 1; int cnt = 0; for (int i = 1; i < n+1; i++) { if (vis[i] == 0){ dfs(i, n+1); cnt++; } } printf("%d\n",max(0,cnt-1)); } }
#使用并查集 #include<iostream> using namespace std; int Tree[1000]; int key[1000]; struct Edge{ int x, y; }edges[1000000]; int findRoot(int x){ if(Tree[x] == -1) return x; else{ int temp = findRoot(Tree[x]); Tree[x] = temp; return temp; } } void combine(int a, int b){ int r_a = findRoot(a); int r_b = findRoot(b); if(r_a != r_b) Tree[r_a] = r_b; } int main(){ int N,M,K; cin>>N>>M>>K; for(int i = 0; i < M; i++){ int a, b; cin>>a>>b; edges[i].x = a; edges[i].y = b; } for(int i = 0; i < K; i++){ cin>>key[i]; } for(int i = 0; i < K; i++){ int k = key[i],counter=0; fill(Tree,Tree+N+1,-1); for(int j = 0; j < M; j++){ if(edges[j].x != k && edges[j].y !=k){ combine(edges[j].x, edges[j].y); } } for(int j = 1; j < N+1; j++) if(Tree[j]==-1) counter++; cout<<((counter-2)>0?counter-2:0)<<endl; } return 0; }
#include <iostream> using namespace std; int main() { int i, j, x, y; int n, m, k; int c1, c2; int count; bool map[1000][1000] = {0}; scanf("%d %d %d", &n, &m, &k); for (i = 0; i < m; ++i) { scanf("%d %d", &c1, &c2); map[c1][c2] = true; map[c2][c1] = true; } for (i = 0; i < k; ++i) { scanf("%d", &c1); count = 0; for (x = 1; x <= n; ++x) { if (x == c1) { continue; } for (y = x+1; y <= n; ++y) { if (y == c1) { continue; } if (map[x][y]) { ++count; } } } count = (n - 2) - count; count = count >= 0 ? count : 0; printf("%d\n", count); } return 0; }
#include<algorithm> #include<cstdio> #include<vector> #include<cstring> #include<iostream> using namespace std; const int maxn=1010; vector<int> G[maxn]; int N,M,K; int delP; bool vis[maxn]={0}; void DFS(int x) { vis[x]=1; for(int i=0;i<G[x].size();i++) { if(vis[G[x][i]]==0 && delP!=G[x][i] ) { DFS(G[x][i]); } } } int main() { cin>>N>>M>>K; //类似于链表 for(int i=0;i<M;i++) { int c1,c2; cin>>c1>>c2; G[c1].push_back(c2); G[c2].push_back(c1); } for(int del=0;del<K;del++) { memset(vis,0,sizeof(vis)); cin>>delP; int block=0; for(int i=1;i<=N;i++) if(vis[i]==false && i!=delP) { DFS(i); block++; } if(block==0) cout<<block<<endl; else cout<<block-1<<endl; } }
就dfs了一下求连通集数量
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
//邻接矩阵
int connect_matrix[1005][1005] = { 0 };
vector<int> result;
bool mark[1005] = { false };
void dfs(int lost, int total, int pos)
{
mark[pos] = true;
for (int i = 1; i <= total; i++) {
if (mark[i] == false && connect_matrix[pos][i] == 1
&& i != lost) {
dfs(lost, total, i);
}
}
}
int main()
{
int M, N, K;
cin >> M >> N >> K;
int start, end;
for (int i = 0; i < N; i++) {
cin >> start >> end;
connect_matrix[start][end] = 1;
connect_matrix[end][start] = 1;
}
int occupied;
int road = 0;
for (int i = 0; i < K; i++) {
cin >> occupied;
memset(mark, false, 1005);
road = 0;
for (int j = 1; j <= M; j++) {
if (mark[j] == false && j != occupied) {
dfs(occupied, M, j);
road++;
}
}
result.push_back(road==0?road:road-1);
}
for (int i = 0; i < result.size(); i++)
cout << result[i] << endl;
return 0;
}
}
{
if (JH[num]==-1) return num;
else
{
int temp= findroot (JH[num],JH);
JH[num]=temp;
return temp;
}
}
#include <iostream>
#include <stdio.h>
int edge[2][10000];
int main( int argc, const char * argv[]) {
int n,m,k;
scanf ( "%d %d %d" ,&n,&m,&k);
int i;
for (i=0;i<m;i++)
{
int a,b;
scanf ( "%d %d" ,&a,&b);
edge [0][i]=a;
edge [1][i]=b;
}
for (i=0;i<k;i++)
{
int city,count=0;
scanf ( "%d" ,&city);
int JH[1001];
int j;
for (j=1;j<=n ;j++)
JH[j]=-1;
for (j=0;j<m;j++)
{
if ( edge [0][j]!=city&& edge [1][j]!=city)
{
int root1= findroot ( edge [0][j],JH);
int root2= findroot ( edge [1][j],JH);
if (root1!=root2)
{
JH[root2]=root1;
}
}
}
JH[city]=0;
for (j=1;j<=n;j++)
{
if (JH[j]==-1)
count++;
}
if (n!=1)
printf ( "%d\n" ,count-1);
else
printf ( "0\n" );
}
return 0;
}
import java.util.Scanner; public class test1013_2 { public static void main(String[] args) { Scanner scanner=new Scanner(System.in); while(scanner.hasNext()){ int citys=scanner.nextInt(); if(citys==1) { System.out.println(0); return; } int roads=scanner.nextInt(); MAX=citys+1; father =new int[MAX]; rank=new int[MAX]; int checked=scanner.nextInt(); int[][] road=new int[roads][2]; for (int i = 0; i < road.length; i++) { road[i][0]=scanner.nextInt(); road[i][1]=scanner.nextInt(); } int[] check=new int[checked]; for (int i = 0; i < checked; i++) { check[i]=scanner.nextInt(); } cal(citys,road,check); } } private static void cal(int citys, int[][] road, int[] check) { int res[]=new int[check.length]; for (int i = 0; i < check.length; i++) { int temp=check[i]; res[i]=citys-2-helper(temp,road,citys); } for (int i = 0; i < res.length; i++) { System.out.println(res[i]); } } private static int helper(int temp, int[][] road, int citys) { int res=0; init();//初始化高度和父节点 for (int i = 0; i < road.length; i++) { int a=road[i][0]; int b=road[i][1]; if(a==temp||b==temp) continue;//删除和temp有关的边 if(Union(a, b)) res++; } return res; } // 初始化秩(树的高度)和父节点 private static void init() { for (int i = 0; i <father.length; i++) { father[i]=i; } for (int i = 0; i < rank.length; i++) { rank[i]=1; } } static int MAX; static int father[]; /* father[x]表示x的父节点*/ static int rank[]; /*rank[x]表示x的秩*/ static int find(int x){ if(father[x]!=x){ father[x]=find(father[x]);//这个回溯时的压缩路径是精华 } return father[x]; } //判断是否Union成功 static boolean Union(int x,int y){ x=find(x); y=find(y); if(x==y) return false; else { if(rank[x]>rank[y]) father[y]=x; else{ if(rank[x]==rank[y]) rank[y]++; father[x]=y; } } return true; } }
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; const int maxn=1005; int n,m,k; bool vis[maxn]; vector<int>v[maxn]; void dfs(int u){ vis[u]=true; for(int i=0;i<v[u].size();i++){ if(!vis[v[u][i]]){ dfs(v[u][i]); } } } int main(){ //freopen("in.txt","r",stdin); scanf("%d%d%d",&n,&m,&k); int from,to,u,ans; for(int i=0;i<m;i++){ scanf("%d%d",&from,&to); v[from].push_back(to); v[to].push_back(from); } for(int i=0;i<k;i++){ fill(vis,vis+n+1,false); ans=-1; scanf("%d",&u); vis[u]=true; for(int i=1;i<=n;i++){ if(!vis[i]){ dfs(i); ans++; } } ans=max(ans,0); printf("%d\n",ans); } return 0; }
#include<cstdio> #include<cstring> #include<vector> #define maxn 1010 using namespace std; vector<int>g[maxn]; bool visit[maxn]; int map[1000][1000]={0}; int n,k,m,a; int concern[1000]; void dfs(int i){ if(i==a)return; if(visit[i]==1)return; visit[i]=1; for(int j=0;j<g[i].size();j++){ dfs(g[i][j]); } } int main(){ scanf("%d%d%d",&n,&m,&k); for(int i=0;i<m;i++){ int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } for(int i=0;i<k;i++){ scanf("%d",&a); memset(visit,0,sizeof(visit)); int block=0; for(int j=1;j<=n;j++){ if(visit[j]==0){ block++; dfs(j); } } printf("%d\n",block-2); } return 0; }bfs搜索并计数联通集的个数,用vector存储图