BZOJ2278: [Poi2011]Garbage
2016-07-09 15:14
281 查看
题目大意:给定n个点m条边,每条边有一个初始权值0或1,有一个最终权值0或1,每次可以给一个简单环上的边权值异或1,求一种方案使得每条边从初始权值变成最终权值
一看这个样子就知道不需要该变的边没啥用,因为反正都要变两次,不如把这两次合起来,然后这些边不变..
然后我就写了一个找欧拉回路的算法,交上去WA了....
然后就要了数据,发现需要特判单独的点,否则会输出一些奇怪的东西....
然后还是WA
TAT||||
为啥题里没说“必须是简单环”啊,这样欧拉回路就不行了....那我们可以维护一个像栈一样的东西遇到一个环就弹出去
再交一发TLE...
然后就想起来毛啸出的那道coloring....也就是邻接表求欧拉回路的时间复杂度会退化到O(N^2)
所以就要用到类似网络流的当前弧优化的东西
一看这个样子就知道不需要该变的边没啥用,因为反正都要变两次,不如把这两次合起来,然后这些边不变..
然后我就写了一个找欧拉回路的算法,交上去WA了....
然后就要了数据,发现需要特判单独的点,否则会输出一些奇怪的东西....
然后还是WA
TAT||||
为啥题里没说“必须是简单环”啊,这样欧拉回路就不行了....那我们可以维护一个像栈一样的东西遇到一个环就弹出去
再交一发TLE...
然后就想起来毛啸出的那道coloring....也就是邻接表求欧拉回路的时间复杂度会退化到O(N^2)
所以就要用到类似网络流的当前弧优化的东西
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #define N 1000010 using namespace std; int to[N<<1],nxt[N<<1],num[N<<1],pre ,cnt; void NO(){puts("NIE");exit(0);} void ae(int ff,int tt) { cnt++; to[cnt]=tt; nxt[cnt]=pre[ff]; pre[ff]=cnt; num[cnt]=(cnt-1)/2; } int du ; bool used ,vis ; int fark; void dfs(int x) { fark++; used[x]=true; int i,j; for(i=pre[x];i;i=nxt[i]) { j=to[i]; if(used[j]) continue; dfs(j); } } vector<int>V ; int tot; bool zai ; int s ,t; void dfs2(int x) { used[x]=true; if(zai[x]) { tot++; V[tot].push_back(x); while(s[t]!=x) { zai[s[t]]=false; V[tot].push_back(s[t]); t--; } zai[s[t]]=false; V[tot].push_back(s[t]); t--; } int i,j; for(i=pre[x];i;i=pre[x]) { pre[x]=nxt[i]; if(!vis[num[i]]) { zai[x]=true; t++;s[t]=x; vis[num[i]]=true; dfs2(to[i]); } } } char ch,B[1<<15],*S=B,*T=B; #define getc() (S==T&&(T=(S=B)+fread(B,1,1<<15,stdin),S==T)?0:*S++) inline int read() { int x=0,f=1;char ch=getc(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();} return x*f; } int main() { int n,m; n=read();m=read(); int i,j,x,y,u,v; while(m--) { x=read();y=read();u=read();v=read(); if(u!=v) { du[x]++;du[y]++; ae(x,y),ae(y,x); } } for(i=1;i<=n;i++) if(du[i]&1) NO(); for(i=1;i<=n;i++) if(!used[i]) dfs2(i); printf("%d\n",tot); for(i=1;i<=tot;i++) { printf("%d ",V[i].size()-1); for(j=0;j<V[i].size();j++) printf("%d ",V[i][j]); puts(""); } }
相关文章推荐
- Binary Tree Maximum Path Sum
- C#的抽象类和接口的区别,在什么时候使用才合适?
- 工具使用-maven 修改默认JDK版本和指定项目JDK版本
- JUNIT实例教程
- 增大胸围!Mr Burning带你在家全方位虐胸!
- Android程序开发意见反馈的实现
- hdu 4550 卡片游戏 贪心 解题报告
- 《孟子》的雄辩
- LCD 显示异常定位分析方法
- php面试题
- LCD 显示异常定位分析方法
- 【Netty4.X】源码分析(三)之LineBasedFrameDecoder
- 剑指offer之面试题19:二叉树的镜像
- Velocity #foreach指令
- Codevs 2370 小机房的树
- 使用windows套接字进行网络编程
- Mysql数据库在cmd操作(一)
- Windows 2008 下 P2V windows 2003系统
- SQL SERVER 2008如何建立自动备份的维护计划
- 去除list里面的重复数组的性能比较