【CodeForces429E】Points and Segments(欧拉回路)
来源:互联网 发布:詹姆斯深蹲力量数据 编辑:程序博客网 时间:2024/05/24 01:54
题目大意
有
题解
用到的欧拉回路性质
先说一说我们在本题中需要用到的一些欧拉回路的一些性质。
(红色是从左往右走,蓝色是从右往左走)
当图的结点都在一个数轴上时,如果存在欧拉回路,
当一个点被一条边从左往右越过,或发出一条像有的边,因为存在环,所以这个点一定被另一条从右往左的边越过,或收到一条向左的边。
这样,每个点向右发出或越过的边一定等于向左接收或越过的边,利用这个性质红蓝染色,就可以解决本题。
注意:一个点接收到的向右的边,或发出的向左的边是没有计算在上述性质中的。
建图
我们需要考虑的是数轴上所有点,而不是整点。
可以发现数轴上很多点的覆盖情况是一样的,所以应该区间一段一段的考虑。
可以发现,这样的区间
与这样的区间
是没有区别的,也就是说,我们可以把右端点右移一点,没有影响。
我们甚至可以把上图的第一条线段的右端点右移到无限逼近与5,但和5中间还是有段空间。
可以把坐标5拆成
然后把上面所说的点当做结点,将线段连边,第一条线段就是
为什么要把原本线段是
因为线段
(实际上,实现时,每个数字并不需要拆成两个点,因为这两个点之间欧拉路直接带过,没有卵用,只是为了方便理解)
连好这些边后,有可能并不存在欧拉回路,因为还有很多奇点,而我们并不能随便把这些奇点连接起来,因为关于这些点的边有可能跨越了大片其它与之不连通的点,乱连会造成错误。(每条欧拉路径,没有环,都会造成一些点,覆盖的两种颜色正好差一,而欧拉路径多了,叠加后可能造成一种颜色过多,如下图,红色太多)
注意到走完欧拉路径,起点和终点两个是奇点,它们这之间一定是颜色覆盖数不相等的,而其他区域都是红蓝相等。
由所以如果从一个奇点走到另一个奇点,中间如果还夹着其它奇点,就会造成中间一个区间,被多个奇点连线覆盖,导致这一区间多次缺少某一颜色。所以如果我们按顺序把相邻的奇点连在一起,就可以避免,原因:
- 如果相邻的奇点是不同连通块,连起来后,连成一个连通块,会成为一个更大的连通块,而这个大连通块要么已经是回路(此时只有这两个奇点之间缺一颜色),要么仍有起点和终点,而起点和终点一定在这两个奇点后面了,永远无法影响此处,这里就完事了。
- 如果相邻的奇点是同一连通块的起点和终点,连接后,以后其它的连通块也不会再影响这里。
所以,总体过程,把输入的线段右端点+1,然后离散化,然后直接连边,把相邻的奇点连边,跑欧拉路。从左往右走的路染红色,从右往左的路染蓝色。
代码
#include<cstdio>#include<algorithm>using namespace std;const int MAXN=400005;int id[MAXN*2],edge[MAXN][2];struct Edge{ int u,v,segid; bool vis; Edge *next,*back;}*V[MAXN*2],E[MAXN*2],*cur=E;void add_edge(int a,int b,int i){ cur->u=a; cur->v=b; cur->segid=i; cur->next=V[a]; cur->back=cur+1; V[a]=cur++; cur->u=b; cur->v=a; cur->segid=i; cur->next=V[b]; cur->back=cur-1; V[b]=cur++;}Edge *path[MAXN*2];int pcnt;void euler(int id){ for(Edge *p=V[id];p;p=p->next) if(!p->vis) { p->vis=1; p->back->vis=1; euler(p->v); path[++pcnt]=p; }}bool vis[MAXN*2];int deg[MAXN*2];int obb[MAXN*2],ocnt;bool ans[MAXN];int main(){ int n,m,l,r; scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",edge[i],edge[i]+1); edge[i][1]++; id[i*2-1]=edge[i][0]; id[i*2]=edge[i][1]; } sort(id+1,id+n*2+1); m=unique(id+1,id+n*2+1)-id-1; for(int i=1;i<=n;i++) { l=lower_bound(id+1,id+m+1,edge[i][0])-id; r=lower_bound(id+1,id+m+1,edge[i][1])-id; add_edge(l,r,i); deg[l]++; deg[r]++; } for(int i=1;i<=m;i++) if(deg[i]&1) obb[++ocnt]=i; for(int i=1;i<=ocnt;i+=2) add_edge(obb[i],obb[i+1],0); for(int i=1;i<=m;i++) if(!vis[i]) { pcnt=0; euler(i); vis[path[pcnt]->u]=1; for(int j=pcnt;j>0;j--) { vis[path[j]->v]=1; ans[path[j]->segid]=(path[j]->u<path[j]->v); } } for(int i=1;i<n;i++) printf("%d ",(int)ans[i]); printf("%d\n",(int)ans[n]); return 0;}
- 【CodeForces429E】Points and Segments(欧拉回路)
- Codeforces 429E Points and Segments 欧拉回路
- [欧拉回路] Codeforces 429E #245 (Div. 1) E. Points and Segments
- 欧拉路AND欧拉回路
- Codeforces Points and Segments (easy)
- Codeforces 430A Points and Segments (easy)
- Codeforces 430 A. Points and Segments (easy)
- Codeforces 430A Points and Segments (easy)
- CodeForces 430A Points and Segments
- 欧拉回路(混合图的欧拉回路)
- HDU 1878 欧拉回路(判断欧拉回路)
- HDU1878欧拉回路(欧拉回路的判定)
- hdoj--5526--欧拉回路(欧拉回路)
- HDU 1878 欧拉回路(欧拉回路)
- hdu1878—欧拉回路(欧拉回路判断)
- HDOJ 1811 欧拉回路 (判断欧拉回路)
- 欧拉回路(欧拉路径)
- 欧拉回路(欧拉路径)
- Windows与linux下caffe配置(仅CPU)
- 观察者模式的C#实现
- Android面试——Fragment相关
- 记一次实现统计访问量最高文章的功能
- 因特网(Internet)与万维网(www)区别
- 【CodeForces429E】Points and Segments(欧拉回路)
- bitset+暴力——校门外的树
- 关于STS工具运行过程中使用Ctrl+right会自动退出的解决办法
- 从mysql 中批量导出数据
- 用ViewHolder优化显示性能
- 伸展树模板
- javaSE之对象相等问题
- 51nod 1122 机器人走方格 V4(矩阵快速幂)
- linux 下常用的解压命令