并查集思想
参考博客
//并查集
#include <iostream>
using namespace std;
int n,m;
int f[510];
int dest[510];//记录此城市是否被攻占
int find(int x){
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
void init(){
for(int i=0;i<510;++i)
f[i]=i;
}
struct nodes{
int a;
int b;
}node[5010];
int fun(int n){//求连通分支数
int cnt=0;
for(int i=0;i<n;++i){
if(f[i]==i)
cnt++;
}
return cnt;
}
void unin(int x,int y){
int p1=find(x);
int p2=find(y);
if(p1!=p2)
f[p1]=p2;
}
int main()
{
init();
cin>>n>>m;
for(int i=0;i<m;++i){
cin>>node[i].a>>node[i].b;
unin(node[i].a,node[i].b);
}
int c1=fun(n);
int k,city;
cin>>k;
while(k--) {//相当于每次都更新一下并查集,求连通分支数量
init();
cin>>city;
dest[city]=1;//当前城市被攻占
for(int i=0;i<m;++i){
//若两个城市中有一个被攻占,则此条边不加入并查集中
if(dest[node[i].a]==1 || dest[node[i].b]==1)
continue;
f[find(node[i].a)]=find(node[i].b);
}
int c2=fun(n);
//判断c1和c2的关系
if(c1==c2 || c2==c1+1){
//连通分支增加2个以上才改变了连通性
cout<<"City "<<city<<" is lost."<<endl;
}else{
cout<<"Red Alert: City "<<city<<" is lost!"<<endl;
}
c1=c2;
}
if(c1==n)
cout<<"Game Over.";
return 0;
}