首先研究环上性质,发现如果状态不变的边就不需要动了,每次改的环上边肯定都是起末状态不同的边且仅改一次,因为如果有一条边在多个环上,相当于没有改,无视这条边之后,这几个环显然可以并成一个大环。所以,我们只关注起末状态不同的边。

然后,这些边形成一张图。对于每个连通块,如果有解的话,应当是一堆边不相交的简单环通过点互相连接的。这样一张图等价于一个欧拉回路,所以只要判每个连通块是不是欧拉回路(偶数度)即可。

然后是求解,目标就是把每个连通块所有的简单环都拎出来。回顾上述欧拉回路判断,实际上正是因为若干简单环构成的图可以一笔画。。所以仿照一笔画过程(也就是栈中记录的访问点顺序),再开一个栈,不断压栈,当遇到一个先前已经压到栈的点的时候说明形成了一个简单环,一直弹栈直到先前点为止,这时弹出元素就构成了一个环。。这样所有环就出来了。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=1e5+,M=1e6+;
struct thxorz{
int head[N],to[M<<],nxt[M<<],tot;
thxorz(){tot=;}
inline void add(int x,int y){
to[++tot]=y,nxt[tot]=head[x],head[x]=tot;
to[++tot]=x,nxt[tot]=head[y],head[y]=tot;
}
}G;
int deg[N],stk[M],vis[M<<],bin[M],bcnt,top,st[N],tp,instk[N];
int n,m,cnt;
#define y G.to[j]
void dfs(int x){//dbg(x);
for(register int&j=G.head[x];j;j=G.nxt[j])if(!vis[j])vis[j]=vis[j^]=,bin[++bcnt]=j,dfs(y);
stk[++top]=x;
}
#undef y
vector<int> ans[M];
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n),read(m);
for(register int i=,x,y,z,w;i<=m;++i){
read(x),read(y),read(z),read(w);
if(z^w)G.add(x,y),++deg[x],++deg[y];
}
for(register int i=;i<=n;++i)if(deg[i]&){puts("NIE");return ;}
for(register int i=;i<=n;++i)if(G.head[i]){
dfs(i);tp=;//dbg(i);
while(bcnt)vis[bin[bcnt]]=vis[bin[bcnt]^]=,--bcnt;
while(top){
int x=stk[top--];//dbg(x);
if(!instk[x])instk[x]=,st[++tp]=x;
else{
ans[++cnt].push_back(x);
do instk[st[tp]]=,ans[cnt].push_back(st[tp--]);while(st[tp]^x);
ans[cnt].push_back(x);
}
}
}
printf("%d\n",cnt);
for(register int i=;i<=cnt;++i,puts("")){
printf("%d ",ans[i].size()-);
for(register int j=;j<ans[i].size();++j)printf("%d ",ans[i][j]);
}
return ;
}

总结:这题启示我们在有关简单环的问题中,除了点双、边双等等转化策略以外,在涉及环的方面也可以采用欧拉路来考虑。总之,解决环相关的问题大概就是点双、边双、欧拉路以及栈的思想、dfs以及二分图染色等方法。

BZOJ2278 [Poi2011]Garbage[欧拉回路求环]的更多相关文章

  1. [POI2011]Garbage 欧拉回路

    [POI2011]Garbage 链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2278 https://loj.ac/problem/216 ...

  2. BZOJ2278 : [Poi2011]Garbage

    如果两个环相交,那么相交的部分相当于没走. 因此一定存在一种方案,使得里面的环都不相交. 把不需要改变状态的边都去掉,剩下的图若存在奇点则无解. 否则,每找到一个环就将环上的边都删掉,时间复杂度$O( ...

  3. Codeforces Round #346 (Div. 2) E - New Reform 无相图求环

    题目链接: 题目 E. New Reform time limit per test 1 second memory limit per test 256 megabytes inputstandar ...

  4. POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环)

    POJ 1860 Currency Exchange / ZOJ 1544 Currency Exchange (最短路径相关,spfa求环) Description Several currency ...

  5. codevs4511信息传递(Tarjan求环)

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  6. poj 2240 Bellman-Flod 求环

    http://poj.org/problem?id=2240 深刻体现了自己代码能力有问题外加改模板能力有问题.外加Debug有问题.以后做到: 1.算法原理能够轻易弄出来. 2.代码模板自己收集各种 ...

  7. AC日记——传话 codevs 1506 (tarjan求环)

    1506 传话  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver 题解       题目描述 Description 一个朋友网络,如果a认识b,那么如果a第 ...

  8. HDU - 6041:I Curse Myself(Tarjan求环&K路归并)

    There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...

  9. 洛谷P2444 [POI2000]病毒(AC自动机,DFS求环)

    洛谷题目传送门 AC自动机入门--yyb巨佬的博客 AC自动机入手经典好题(虽然年代久远) 有了fail指针,trie树就不是原来的树型结构了,我们可以把它叫做trie图,由父节点向子节点连的边和fa ...

随机推荐

  1. rest_framework之序列化组件

    什么是rest_framework序列化? 在写前后端不分离的项目时: 我们有form组件帮我们去做数据校验 我们有模板语法,从数据库取出的queryset对象不需要人为去转格式 当我们写前后端分离项 ...

  2. idea开发shell脚本并运行

    参考:https://blog.csdn.net/u012443641/article/details/81295999 IEDA中的bashsupport插件支持在IDEA中编写shell脚本文件, ...

  3. [学习笔记] Hibernate 4.3.5 下载与安装

    下载 http://hibernate.org/orm/releases/4.3/ https://sourceforge.net/projects/hibernate/files/hibernate ...

  4. AndroidStudio下载安装教程(图文教程)

    场景 Android Studio 中文社区: http://www.android-studio.org/ 下载安装包,这里选择64位Windows 等待下载完成. 注: 博客: https://b ...

  5. SQL SERVER 字符串函数 PATINDEX()

    定义: PATINDEX()返回模式在指定表达式中第一次出现的起始位置:如果在所有有效的文本和字符数据类型中都找不到该模式,则返回零. 语法: PATINDEX ( '%pattern%' , exp ...

  6. CREATE TABLE——数据定义语言 (Data Definition Language, DDL)

    Sql语句分为三大类: 数据定义语言,负责创建,修改,删除表,索引和视图等对象: 数据操作语言,负责数据库中数据的插入,查询,删除等操作: 数据控制语言,用来授予和撤销用户权限. 数据定义语言 (Da ...

  7. javaweb中关于转发与重定向的写法

    转发: RequestDispatcher rd = request.getRequestDispatcher("/WEB-INF/main.jsp"); rd.forward(r ...

  8. 关于typescript中的枚举你需要知道这些

    数字枚举 数字枚举,即枚举里所有属性的值都是数字类型,先看这段代码: enum Colors { Red, Blue, Yellow } console.log(Colors.Red) console ...

  9. java日志框架系列(2):logback框架详解

    1.logback介绍 1.什么是logback Logback 为取代 log4j 而生. Logback 由 log4j 的创立者 Ceki Gülcü设计.以十多年设计工业级记录系统的经验为基础 ...

  10. 如何判断你的windows系统是32位还是64位?

    [学习笔记] 如 何判断你的windows系统是32位还是64位? java -version时,如果没有64就是32位的.eclipse.ini中如果没有64,就是32位的.但是我们的ini文件里面 ...