UOJ_14_【UER #1】DZY Loves Graph_並查集
阿新 • • 發佈:2018-08-12
mes pro names sta 樹邊 std 存在 ace namespace
UOJ_14_【UER #1】DZY Loves Graph_並查集
題面:http://uoj.ac/problem/14
考慮只有前兩個操作怎麽做。
每次刪除一定是從後往前刪,並且被刪的邊如果不是樹邊則沒有影響,如果是樹邊也不存在邊能替代。
直接刪除這條邊就可以。
於是用一個棧來保存現場,然後按秩合並的並查集維護就OK了。
現在有撤回操作,但根據上面對刪邊分析出的性質。
可以這樣:
如果是插入一條邊,然後撤回,相當於刪邊。
如果刪邊然後撤回,相當於什麽也不做。
代碼還是很好理解的。
代碼:
#include <cstdio> #include <cstring> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; typedef long long ll; #define N 500050 inline char nc() { static char buf[100000],*p1,*p2; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } int rd() { int x=0; char s=nc(); while(s<‘0‘||s>‘9‘) s=nc(); while(s>=‘0‘&&s<=‘9‘) x=(x<<3)+(x<<1)+s-‘0‘,s=nc(); return x; } char rc() { char s=nc(); while(s!=‘A‘&&s!=‘D‘&&s!=‘R‘&&s!=EOF) s=nc(); return s; } int fa[N],S[N],top,ec[N],n,m,siz[N]; ll ev[N]; int find(int x) {return fa[x]==x?x:find(fa[x]);} inline void output(int x) {printf("%lld\n",ec[x]==n-1?ev[x]:0ll);} void add(int x,int y,int z) { int dx=find(x),dy=find(y); top++; ec[top]=ec[top-1]; ev[top]=ev[top-1]; if(dx==dy) S[top]=0; else { if(siz[dx]>siz[dy]) swap(dx,dy); S[top]=dx; fa[dx]=dy; siz[dy]+=siz[dx]; ec[top]++; ev[top]+=z; } } void del(int K) { while(K--) { int t=S[top--]; siz[fa[t]]-=siz[t]; fa[t]=t; } } int main() { n=rd(); m=rd(); int i,x,y; for(i=1;i<=n;i++) fa[i]=i,siz[i]=1; char s=rc(); for(i=1;i<=m;i++) { if(s==‘A‘) { x=rd(); y=rd(); add(x,y,i); output(top); s=rc(); if(s==‘R‘) del(1); }else if(s==‘D‘) { x=rd(); output(top-x); s=rc(); if(s!=‘R‘) del(x); }else { output(top); s=rc(); } } }
UOJ_14_【UER #1】DZY Loves Graph_並查集