P5157 [USACO18DEC]The Cow Gathering
阿新 • • 發佈:2019-01-27
全部 long 就是 i++ ring ios str tchar ace
按照上述方法只能判斷出2,3,4,5不合法。
事實上因為在上述方法中,只考慮了每條邊自己單一的影響,而沒有考慮它們組合起來的影響。
胡亂分析發現,它們組合起來產生的影響要麽是沒影響,要麽就是所有點都無法被留到最後一個刪除。
這樣的話,只需要特判一下是否整個圖的無法被留到最後一個刪除即可。
可以用類似拓撲排序的方法來判斷。
首先考慮怎麽check一個點是否能被最後一個刪除。
可以這麽建圖,以這個點建有根樹,邊全部向上指,再加上剩下的有向邊。
很明顯,這裏的一條邊的定義就變成了只有刪去這個點,才可以刪去它指向的點。
因此,只需要建n次圖暴力判斷是否有環即可。
這樣做是n^2的。
考慮加入一條邊後,會產生什麽影響。
發現這條邊會導致一些點答案直接被欽定為零(這些點滿足以它們為根一定會存在環)
設邊為u---->v
具體分析一下,這些點是所有以v為根建有根樹後,u子樹內的所有點。
這個可以通過類似換根的分類討論的方法來找到這些點,它們構成了幾段(O(1)級別)區間。
直接差分欽定它們答案為0即可。
然而這樣做是有bug的。
考慮這樣一個圖
按照上述方法只能判斷出2,3,4,5不合法。
事實上因為在上述方法中,只考慮了每條邊自己單一的影響,而沒有考慮它們組合起來的影響。
胡亂分析發現,它們組合起來產生的影響要麽是沒影響,要麽就是所有點都無法被留到最後一個刪除。
這樣的話,只需要特判一下是否整個圖的無法被留到最後一個刪除即可。
可以用類似拓撲排序的方法來判斷。
#include<iostream> #include<cctype> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<queue> #include<cstdlib> #include<algorithm> #define N 220000 #define L 200000 #define eps 1e-7 #define inf 1e9+7 #define db double #define ll long long #define ldb long double using namespace std; inline int read() { char ch=0; int x=0,flag=1; while(!isdigit(ch)){ch=getchar();if(ch==‘-‘)flag=-1;} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-‘0‘;ch=getchar();} return x*flag; } struct edge{int to,nxt;}e[N*2],E[N*2]; int num,head[N],NUM,HEAD[N]; inline void add(int x,int y){e[++num]=(edge){y,head[x]};head[x]=num;} inline void ADD(int X,int Y){E[++NUM]=(edge){Y,HEAD[X]};HEAD[X]=NUM;} queue<int>q; bool vis[N]; int times,c[N],sz[N],deg[N],deg_[N],dep[N],dfn[N],nxt[N][25]; void dfs(int x,int fa) { sz[x]=1;dfn[x]=++times;dep[x]=dep[fa]+1; for(int i=head[x];i!=-1;i=e[i].nxt) { int to=e[i].to; if(to==fa)continue; dfs(to,x);sz[x]+=sz[to];nxt[to][0]=x; } } int get(int x,int k){for(int i=0;i<=20;i++)if(1<<i&k)x=nxt[x][i];return x;} int main() { num=NUM=-1;memset(head,-1,sizeof(head));memset(HEAD,-1,sizeof(HEAD)); int n=read(),m=read(),tot=0; for(int i=1;i<n;i++){int x=read(),y=read();add(x,y);add(y,x);deg[x]++;deg[y]++;} dfs(1,1); for(int k=1;k<=20;k++)for(int i=1;i<=n;i++)nxt[i][k]=nxt[nxt[i][k-1]][k-1]; for(int i=1;i<=m;i++) { int x=read(),y=read(); ADD(x,y);deg_[y]++; int l=dfn[x],r=dfn[x]+sz[x]-1; if(l<=dfn[y]&&dfn[y]<=r) { int to=get(y,dep[y]-dep[x]-1); int pl=dfn[to],pr=dfn[to]+sz[to]-1; c[pl]--;c[pr+1]++;c[1]++;c[n+1]--; } else c[l]++,c[r+1]--; } for(int i=1;i<=n;i++)if(deg[i]==1&&!deg_[i])q.push(i); while(!q.empty()) { int x=q.front();q.pop(); if(vis[x])continue;vis[x]=true;tot++; for(int i=head[x];i!=-1;i=e[i].nxt){int to=e[i].to;deg[x]--;deg[to]--;} for(int i=HEAD[x];i!=-1;i=E[i].nxt){int to=E[i].to;deg_[to]--;} for(int i=head[x];i!=-1;i=e[i].nxt){int to=e[i].to;if(deg[to]==1&&!deg_[to])q.push(to);} for(int i=HEAD[x];i!=-1;i=E[i].nxt){int to=E[i].to;if(deg[to]==1&&!deg_[to])q.push(to);} } if(tot<n){for(int i=1;i<=n;i++)printf("0\n");return 0;} for(int i=1;i<=n;i++)c[i]+=c[i-1]; for(int i=1;i<=n;i++)printf("%d\n",c[dfn[i]]?0:1); return 0; }
P5157 [USACO18DEC]The Cow Gathering