[agc14e]Blue and Red Tree
来源:互联网 发布:zola算法美队2 编辑:程序博客网 时间:2024/05/14 20:50
前言
这题主要是要想到倒过来,是一个很唯一的过程。
我大概想到了,但我比题解蠢。
题解的不需要区分红蓝让我觉得很机智。
题意
有一颗全是蓝边的树,你对其执行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");}
阅读全文
0 0
- [agc14e]Blue and Red Tree
- [AtCoder AGC014 .E][杂题]Blue and Red Tree
- 【AGC014E】Blue and Red Tree 并查集 启发式合并
- hdu4263 Red/Blue Spanning Tree
- hdu4263 Red/Blue Spanning Tree
- Red/Blue Spanning Tree----HDU_4263----并查集and生成树
- hdu 4263 Red/Blue Spanning Tree
- [HDU 4263]Red/Blue Spanning Tree[kruskal]
- hdu 4263 Red/Blue Spanning Tree
- 【图论】【匹配】pku3715 Blue and Red
- codeforces#233_div2_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-取边贪心)
- 并查集-- HDU - 4263 Red/Blue Spanning Tree
- [PKU 3715]Blue and Red(最小点覆盖集)
- poj3715——Blue and Red//最小顶点覆盖
- 基于OpenCV的RGB和HSV色彩空间相互转换C++程序
- java 常用集合list与Set、Map区别及适用场景总结
- preparedStatement和Statement的区别
- MongoDB&C++开发 (三) C++ Driver 浅析(结合mongo-cxx-driver/examples中代码)
- Python 正则表达式匹配字符串替换、格式修改
- [agc14e]Blue and Red Tree
- vim替换命令
- HDU1050-Moving Table
- 用jquery制作轮播图
- BZOJ2125: 最短路
- linux基础练习
- HTML知识点总结
- POJ 1743 Musical Theme(不可重叠最长重复子串 后缀数组)
- C#分页Dome