USACO 2016 US Open Contest, Silver
Problem 3
题目背景
题目描述
FJ 和他的奶牛们正在计划离开小镇做一次长的旅行,同时 FJ 想临时地关掉他的农场以节省一些金钱。
这个农场一共有被用 M 条双向道路连接的 N 个谷仓(1≤N,M≤3000)。为了关闭整个农场,FJ 计划每一次关闭掉一个谷仓。当一个谷仓被关闭了,所有的连接到这个谷仓的道路都会被关闭,而且再也不能够被使用。
FJ 现在正感兴趣于知道在每一个时间(这里的“时间”指在每一次关闭谷仓之后的时间)时他的农场是否是“全连通的”——也就是说从任意的一个开着的谷仓开始,能够到达另外的一个谷仓。注意自从某一个时间之后,可能整个农场都开始不会是“全连通的”。
输入格式
输入的第一行是两个整数 N 和 M ;
下面的 M 行每行都描述了一条连接两个谷仓的双向路径的两个端点(输入的点保证在 1...N 的范围内);
最后的 N 行是一个 1...N 的排列,描述每一个谷仓被关闭的顺序。
输出格式
输出一共有 N 行,每行可以是“YES”或者“NO”。
第一行表示一开始时整个农场是否是“全连通的”;
然后第 i+1 行表示在第 i 次的关闭谷仓之后整个农场是否是“全连通的”。
样例数据 1
输入
4 3
1 2
2 3
3 4
3
4
1
2
输出
YES
NO
YES
YES
#include<iostream> #include<cstdio> #include<cstring> using namespace std; struct node{ int to[3001]; int time; bool close; }edge[3010]; int n,m,count; int close[3010]; bool going[3010]; inline int readint() { int i=0,f=1; char ch; for(ch=getchar();ch<'0'||ch>'9';ch=getchar()); for(;ch>='0' && ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0'; return i*f; } inline int add(int x,int y) { ++edge[x].time; edge[x].to[edge[x].time]=y; } inline void go(int begin) { going[begin]=true; ++count; for(int i=1;i<=edge[begin].time;++i) if(!going[edge[begin].to[i]]&&!edge[edge[begin].to[i]].close) go(edge[begin].to[i]); } int main() { int x,y; n=readint(); m=readint(); for(int i=1;i<=m;++i) { x=readint(); y=readint(); add(x,y); add(y,x); } for(int i=1;i<=n;++i) close[i]=readint(); int k=0; do { count=0; edge[close[k]].close=true; for(int i=1;i<=n;++i) if(!edge[i].close) { memset(going,false,sizeof(going)); go(i); break; } if(count==(n-k)) puts("YES"); else puts("NO"); ++k; }while(close[k+1]); return 0; }
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> using namespace std; struct hh{int u,v,next; }ma[1000000]; int nb=0,father[500000],d[500000],x,y,nu[500000],first[500000],n,m; bool check1[500000],check2[500000]; void crea(int u,int v) { ma[++nb].next=first[u]; ma[nb].u=u; ma[nb].v=v; first[u]=nb; } int ffa(int x) { if(father[x]!=x) return father[x]=ffa(father[x]); return x; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); cin>>n>>m; memset(first,0,sizeof(first)); memset(check1,false,sizeof(check1)); memset(check2,false,sizeof(check2)); for(int i=1;i<=m;++i) { cin>>x>>y; crea(x,y); crea(y,x); } for(int i=n;i>0;i--) { cin>>d[i]; father[i]=i; nu[i]=1; } for(int i=1;i<=n;++i) { x=ffa(d[i]); check2[d[i]]=true; for(int j=first[d[i]];j>0;j=ma[j].next) { if(!check2[ma[j].v]) continue; y=ffa(ma[j].v); if(x!=y) { father[y]=x; nu[x]+=nu[y]; } } if(nu[x]==i) { check1[n-i+1]=true; } } for(int i=1;i<=n;++i) if(check1[i]) cout<<"YES"<<endl; else cout<<"NO"<<endl; }