题目大意:
n个谷仓 ,每次关闭一个谷仓,问剩下没被关闭的谷仓是
否联通。
题解:并查集+倒序处理
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 3030 using namespace std; int n,m,sumedge,cnt; int head[N],fa[N],q[N],ans[N],exit[N]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[N<<1]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } int f(int x){ return fa[x]==x?x:fa[x]=f(fa[x]); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=n;i++)fa[i]=i;cnt=n; for(int i=1;i<=n;i++)scanf("%d",&q[i]); for(int i=n;i>=1;i--){ int x=q[i];exit[x]=true; for(int h=head[x];h;h=edge[h].nxt){ int v=edge[h].y; if(exit[v]==0)continue; int fx=f(x),fy=f(v); if(fx!=fy){ fa[fx]=fy; cnt--; } } if(cnt==i)ans[i]=true; } for(int i=1;i<=n;i++) if(ans[i])puts("YES"); else puts("NO"); return 0; }
并查集
#include<iostream> #include<cstdio> #include<cstring> #define N 3009 using namespace std; int n,m,cnt; int q[N],exit[N],ans[N],d[N][N]; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ int x,y; scanf("%d%d",&x,&y); d[x][y]=d[y][x]=true; } for(int i=1;i<=n;i++)scanf("%d",&q[i]); for(int i=n;i>=1;i--){ bool flag=false; int now=q[i]; exit[++cnt]=now; for(int k=1;k<=cnt;k++){ for(int j=1;j<=cnt;j++){ for(int p=1;p<=cnt;p++){ d[exit[j]][exit[p]]=d[exit[j]][exit[p]]||(d[exit[j]][exit[k]]&&d[exit[k]][exit[p]]); } } } for(int j=1;j<=cnt;j++){ for(int p=j+1;p<=cnt;p++){ if(d[exit[j]][exit[p]]==0){ ans[i]=0;flag=true; break; } } } if(flag==false){ ans[i]=1; } } for(int i=1;i<=n;i++) if(ans[i])printf("YES\n"); else printf("NO\n"); return 0; }
50暴力
时间: 2024-11-08 12:39:27