首先计算初始连通块的数量,然后每次将被攻打的城市标记,再重新计算连通块的数量,如果连通块的数量增加一个以上,说明该城市会改变国家的连通性,否则不会改变国家的连通性。
【并查集】
#include<iostream>
#include<cmath>
using namespace std;
const int N=520;
int p[N];
int n,m;
struct str
{
int l;
int r;
}arr[5010];
int find(int x)
{
if(p[x]!=x) return p[x]=find(p[x]);
return p[x];
}
void init()//初始化
{
for(int i=0;i<n;i++) p[i]=i;
}
void add(int x,int y)
{
if(find(x)!=find(y))
{
p[find(x)]=find(y);
}
}
int count()//计算连接块的数量
{
int ans=0;
for(int i=0;i<n;i++)
{
if(p[i]==i) ans++;
}
return ans;
}
void fun()
{
for(int i=1;i<=m;i++)
{
if(arr[i].l==-1||arr[i].r==-1) continue;
add(arr[i].l,arr[i].r);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>arr[i].l>>arr[i].r;
}
init();
fun();
int ans1=count();//计算初始连通块的数量
int k;
cin>>k;
int t=k;
while(t--)
{
int a;
cin>>a;
init();
for(int i=1;i<=m;i++)
{
if(arr[i].l==a||arr[i].r==a)
{
arr[i].l=-1;
arr[i].r=-1;
}
}
fun();
int ans2=count();
//如果连通块数量增加一个以上,说明该城市会改变城市的连通性;
if(abs(ans1-ans2)>1) printf("Red Alert: City %d is lost!\n",a);
else printf("City %d is lost.\n",a);
ans1=ans2;
}
if(k==n) cout<<"Game Over."<<endl;
return 0;
}
【DFS】
#include<iostream>
#include<cstring>
using namespace std;
const int N=520,M=5020;
int a[N][N];
bool st[N];
int n,m;
void dfs(int u)
{
st[u]=true;
for(int i=0;i<n;i++)
{
if((a[u][i]||a[i][u])&&!st[i]) dfs(i);
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
a[x][y]=a[y][x]=1;
}
int cnt=0;
for(int i=0;i<n;i++)
{
if(!st[i]) cnt++,dfs(i);
}
int ans1=cnt;
int t;
cin>>t;
int tt=t;
while(t--)
{
memset(st,false,sizeof st);
int k;
cin>>k;
for(int i=0;i<n;i++)
{
if(a[i][k]||a[k][i])
{
a[i][k]=a[k][i]=0;
}
}
int ans2=0;
for(int i=0;i<n;i++)
{
if(!st[i]) ans2++,dfs(i);
}
if(ans2-ans1>1) printf("Red Alert: City %d is lost!\n",k);
else printf("City %d is lost.\n",k);
ans1=ans2;
}
if(tt==n) printf("Game Over.");
return 0;
}