[agc14e]Blue and Red Tree
2017-09-27 22:13
453 查看
前言
这题主要是要想到倒过来,是一个很唯一的过程。我大概想到了,但我比题解蠢。
题解的不需要区分红蓝让我觉得很机智。
题意
有一颗全是蓝边的树,你对其执行n-1次操作。每次操作选择一条全是蓝边的路径,将其中的一条蓝边断开,假设选择的路径是j->k,断的边是x-y,且断开后j和x联通,那么k和y联通。
然后你需要选择j->x上的一个节点,以及k->y上的一个节点,在这两个节点间连红边。
现在问你能否存在方案变着指定的全是红边的树。
题解
考虑倒过来加边。这个过程是很唯一的。
首先一开始有很多单点联通块。
每次如果两个联通块之间存在蓝边与红边相连,合并两个联通块。
最后合并成一个就行了。
好实现的方法是,这个红和蓝我们可以认为没有区别。
于是可以用一个queue存需要合并的联通块对(即之间存在两条边),用map来存两个联通块间的边数,用set存与某个联通块存在边的联通块,用并查集来维护连通性,合并两个联通块只需要启发式合并即可。
这样真好写!
#include<cstdio> #include<algorithm> #include<set> #include<map> #include<queue> #define fo(i,a,b) for(i=a;i<=b;i++) using namespace std; const int maxn=100000+10; typedef pair<int,int> pi; pi zlt; map<pi,int> cnt,bz; set<int> s[maxn]; set<int>::iterator it; queue<pi> dl; int fa[maxn]; int i,j,k,l,t,n,m,x,y,z,ca; bool czy; int getfa(int x){ return fa[x]?fa[x]=getfa(fa[x]):x; } int main(){ scanf("%d",&n); fo(i,1,2*(n-1)){ scanf("%d%d",&j,&k); if (j>k) swap(j,k); zlt=make_pair(j,k); cnt[zlt]++; if (cnt[zlt]==1){ s[j].insert(k); s[k].insert(j); } if (cnt[zlt]>1&&!bz[zlt]){ dl.push(zlt); bz[zlt]=1; } } czy=1; ca=n-1; while (ca--){ x=y=-1; while (!dl.empty()){ j=getfa(dl.front().first); k=getfa(dl.front().second); dl.pop(); if (j!=k){ x=j;y=k; break; } } if (x==y&&x==-1){ czy=0; break; } if (s[x].size()<s[y].size()) swap(x,y); fa[y]=x; it=s[y].begin(); while (it!=s[y].end()){ z=*it; it++; s[z].erase(s[z].find(y)); if (z==x) continue; //if (s[x].find(z)==s[x].end()) s[x].insert(z),s[z].insert(x); if (x<z) zlt=make_pair(x,z);else zlt=make_pair(z,x); cnt[zlt]++; if (cnt[zlt]==1){ s[x].insert(z); s[z].insert(x); } if (cnt[zlt]>1&&!bz[zlt]){ dl.push(zlt); bz[zlt]=1; } } s[y].clear(); } if (czy) printf("YES\n");else printf("NO\n"); }
相关文章推荐
- 【AGC014】E - Blue and Red Tree
- Red/Blue Spanning Tree----HDU_4263----并查集and生成树
- AtCoder AGC14E-Blue and Red Tree 并查集+启发式合并+STL
- [AtCoder AGC014 .E][杂题]Blue and Red Tree
- AtCoder Grand Contest 014 E - Blue and Red Tree 乱搞
- 【AGC014E】Blue and Red Tree 并查集 启发式合并
- 【CodeForces 339B】Red and Blue Balls 找规律
- codeforces#233_div2_B Red and Blue Balls
- pku3715 Blue and Red
- HDU 4263 Red/Blue Spanning Tree【最小生成树原理】
- HDU 4263 Red/Blue Spanning Tree
- cf B Red and Blue Balls
- POJ 3715 Blue and Red 二分图
- hdu 4263 Red/Blue Spanning Tree
- HDU-#4263 Red/Blue Spanning Tree(Kruskal)
- 并查集-- HDU - 4263 Red/Blue Spanning Tree
- poj 3715 Blue and Red(二分图最大匹配匈牙利算法)
- [CC-BLREDSET]Black and Red vertices of Tree
- Codeforces Round #233 (Div. 2) B. Red and Blue Balls
- hdu4263 Red/Blue Spanning Tree