POJ1637 Sightseeing tour(判定混合图欧拉回路)
有向连通图存在欧拉回路的充要条件是所有点入度=出度。
首先随便给定所有无向边一个方向(不妨直接是u->v方向),记录所有点的度(记:度=入度-出度)。
这时如果有点的度不等于0,那么就不存在欧拉回路,就需要改变那些无向边的方向。
而改变一个无向边的方向,相当于边上两个端点的入度和出度都变化了1,它们的度±2。
另外,这样可以证明如果这时某个点的度为奇数那么一定不存在存在欧拉回路的解。
构图如下:所有无向边(u,v),建立容量为1的(u,v)边;所有度小于0的点u,建立容量为-deg/2的(vs,u)边;所有度大于0的点u,建立容量为deg/2(u,vt)边。
最后如果和vs、vt关联的边都满流,那么就有存在欧拉回路的解。
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 222
#define MAXM 4444 struct Edge{
int v,cap,flow,next;
}edge[MAXM];
int vs,vt,NE,NV;
int head[MAXN]; void addEdge(int u,int v,int cap){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=; edge[NE].flow=;
edge[NE].next=head[v]; head[v]=NE++;
} int level[MAXN];
int gap[MAXN];
void bfs(){
memset(level,-,sizeof(level));
memset(gap,,sizeof(gap));
level[vt]=;
gap[level[vt]]++;
queue<int> que;
que.push(vt);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(level[v]!=-) continue;
level[v]=level[u]+;
gap[level[v]]++;
que.push(v);
}
}
} int pre[MAXN];
int cur[MAXN];
int ISAP(){
bfs();
memset(pre,-,sizeof(pre));
memcpy(cur,head,sizeof(head));
int u=pre[vs]=vs,flow=,aug=INF;
gap[]=NV;
while(level[vs]<NV){
bool flag=false;
for(int &i=cur[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[u]==level[v]+){
flag=true;
pre[v]=u;
u=v;
//aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap));
aug=min(aug,edge[i].cap-edge[i].flow);
if(v==vt){
flow+=aug;
for(u=pre[v]; v!=vs; v=u,u=pre[u]){
edge[cur[u]].flow+=aug;
edge[cur[u]^].flow-=aug;
}
//aug=-1;
aug=INF;
}
break;
}
}
if(flag) continue;
int minlevel=NV;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap!=edge[i].flow && level[v]<minlevel){
minlevel=level[v];
cur[u]=i;
}
}
if(--gap[level[u]]==) break;
level[u]=minlevel+;
gap[level[u]]++;
u=pre[u];
}
return flow;
} int n,m,deg[MAXN];
bool solve(){
for(int i=; i<=n; ++i){
if(abs(deg[i])&) return ;
if(deg[i]>) addEdge(i,vt,deg[i]>>);
else if(deg[i]<) addEdge(vs,i,(-deg[i])>>);
}
ISAP();
for(int i=; i<NE ;i+=){
if(edge[i^].v!=vs&&edge[i].v!=vt) continue;
if(edge[i].cap!=edge[i].flow) return ;
}
return ;
}
int main(){
int t,a,b,c;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
vs=; vt=n+; NV=vt+; NE=;
memset(head,-,sizeof(head));
memset(deg,,sizeof(deg));
while(m--){
scanf("%d%d%d",&a,&b,&c);
--deg[a]; ++deg[b];
if(c==) addEdge(a,b,);
}
if(solve()) puts("possible");
else puts("impossible");
}
return ;
}
POJ1637 Sightseeing tour(判定混合图欧拉回路)的更多相关文章
- [POJ1637]Sightseeing tour:混合图欧拉回路
分析 混合图欧拉回路问题. 一个有向图有欧拉回路当且仅当图连通并且对于每个点,入度\(=\)出度. 入度和出度相等可以联想到(我也不知道是怎么联想到的)网络流除了源汇点均满足入流\(=\)出流.于是可 ...
- Sightseeing tour 【混合图欧拉回路】
题目链接:http://poj.org/problem?id=1637 Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total ...
- POJ 1637 Sightseeing tour(混合图欧拉回路+最大流)
http://poj.org/problem?id=1637 题意:给出n个点和m条边,这些边有些是单向边,有些是双向边,判断是否能构成欧拉回路. 思路: 构成有向图欧拉回路的要求是入度=出度,无向图 ...
- POJ 1637 Sightseeing tour (混合图欧拉路判定)
Sightseeing tour Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 6986 Accepted: 2901 ...
- [Poi2010]Bridges 最大流+二分答案 判定混合图欧拉回路
https://darkbzoj.cf/problem/2095 bzoj 相同的题挂了,这个oj可以写. 题目就是要我们找一条欧拉回路(每个桥经过一次就好,不管方向),使得这条回路上权值最大的尽量小 ...
- poj1637 Sightseeing tour(混合图欧拉回路)
题目链接 题意 给出一个混合图(有无向边,也有有向边),问能否通过确定无向边的方向,使得该图形成欧拉回路. 思路 这是一道混合图欧拉回路的模板题. 一张图要满足有欧拉回路,必须满足每个点的度数为偶数. ...
- POJ 1637 - Sightseeing tour - [最大流解决混合图欧拉回路]
嗯,这是我上一篇文章说的那本宝典的第二题,我只想说,真TM是本宝典……做的我又痛苦又激动……(我感觉ACM的日常尽在这张表情中了) 题目链接:http://poj.org/problem?id=163 ...
- POJ 1637 Sightseeing tour ★混合图欧拉回路
[题目大意]混合图欧拉回路(1 <= N <= 200, 1 <= M <= 1000) [建模方法] 把该图的无向边随便定向,计算每个点的入度和出度.如果有某个点出入度之差为 ...
- poj1637Sightseeing tour(混合图欧拉回路)
题目请戳这里 题目大意:求混合图欧拉回路. 题目分析:最大流.竟然用网络流求混合图的欧拉回路,涨姿势了啊啊.. 其实仔细一想也是那么回事.欧拉回路是遍历所有边一次又回到起点的回路.双向图只要每个点度数 ...
随机推荐
- css去掉iPhone、iPad默认按钮样式
原文链接:http://blog.sina.com.cn/s/blog_7d796c0d0102uyd2.html 只要在样式里面加一句去掉css去掉iPhone.iPad的默认按钮样式就可以了!~ ...
- 解决客户端访问https报错
现象: javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure at com.sun.net.ssl. ...
- UITableView的scrollToRowAtIndexPath:atScrollPosition:animated的崩溃
UITableView的scrollToRowAtIndexPath:atScrollPosition:animated的崩溃 [摘要:reason: '-[UITableView _conten ...
- viewpager中彻底性动态添加、删除Fragment
为了解决彻底删除fragment,我们要做的是:1.将FragmentPagerAdapter 替换成FragmentStatePagerAdapter,因为前者只要加载过,fragment中的视图就 ...
- Swift - 简单封装一个工具类模板
创建模板类(封装一个类) 例1:新建一个名字叫做 Product 的类 Product.swift File 的内容 class Product { var name: String var desc ...
- 与你相遇好幸运,My Toolkit of Nodejs
>测试:restler.mocha.assert.request.request-promise >安装:nrm >运维:pm2.node-gyp >开发:nodemon.in ...
- win10总是自动重启的解决办法
win10总是自动重启的解决办法_百度经验http://jingyan.baidu.com/article/7908e85c983523af481ad214.html
- mac os x使用技巧及常用软件
常见键盘符号:⌘(command).⌥(option).⇧(shift).⇪(caps lock).⌃(control) 常用快捷键 复制 Command+c / Option+拖拽 粘贴 Com ...
- Python科学计算发行版—Anaconda
Python是一种强大的编程语言,其提供了很多用于科学计算的模块,常见的包括numpy.scipy和matplotlib.要利用Python进行科学计算,就需要一一安装所需的模块,而这些模块可能又依赖 ...
- JavaScript - 基本概念
相等操作符 == 和 != 是先转换再比较 === 和 !== 是直接比较,不经过转换 中文翻译上来说叫做相等和全等.类型转换简单的概括就是高级转低级,比如说布尔字符串转数字,对象取值再转.相等比较有 ...