有向连通图存在欧拉回路的充要条件是所有点入度=出度。

首先随便给定所有无向边一个方向(不妨直接是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(判定混合图欧拉回路)的更多相关文章

  1. [POJ1637]Sightseeing tour:混合图欧拉回路

    分析 混合图欧拉回路问题. 一个有向图有欧拉回路当且仅当图连通并且对于每个点,入度\(=\)出度. 入度和出度相等可以联想到(我也不知道是怎么联想到的)网络流除了源汇点均满足入流\(=\)出流.于是可 ...

  2. Sightseeing tour 【混合图欧拉回路】

    题目链接:http://poj.org/problem?id=1637 Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total ...

  3. POJ 1637 Sightseeing tour(混合图欧拉回路+最大流)

    http://poj.org/problem?id=1637 题意:给出n个点和m条边,这些边有些是单向边,有些是双向边,判断是否能构成欧拉回路. 思路: 构成有向图欧拉回路的要求是入度=出度,无向图 ...

  4. POJ 1637 Sightseeing tour (混合图欧拉路判定)

    Sightseeing tour Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6986   Accepted: 2901 ...

  5. [Poi2010]Bridges 最大流+二分答案 判定混合图欧拉回路

    https://darkbzoj.cf/problem/2095 bzoj 相同的题挂了,这个oj可以写. 题目就是要我们找一条欧拉回路(每个桥经过一次就好,不管方向),使得这条回路上权值最大的尽量小 ...

  6. poj1637 Sightseeing tour(混合图欧拉回路)

    题目链接 题意 给出一个混合图(有无向边,也有有向边),问能否通过确定无向边的方向,使得该图形成欧拉回路. 思路 这是一道混合图欧拉回路的模板题. 一张图要满足有欧拉回路,必须满足每个点的度数为偶数. ...

  7. POJ 1637 - Sightseeing tour - [最大流解决混合图欧拉回路]

    嗯,这是我上一篇文章说的那本宝典的第二题,我只想说,真TM是本宝典……做的我又痛苦又激动……(我感觉ACM的日常尽在这张表情中了) 题目链接:http://poj.org/problem?id=163 ...

  8. POJ 1637 Sightseeing tour ★混合图欧拉回路

    [题目大意]混合图欧拉回路(1 <= N <= 200, 1 <= M <= 1000) [建模方法] 把该图的无向边随便定向,计算每个点的入度和出度.如果有某个点出入度之差为 ...

  9. poj1637Sightseeing tour(混合图欧拉回路)

    题目请戳这里 题目大意:求混合图欧拉回路. 题目分析:最大流.竟然用网络流求混合图的欧拉回路,涨姿势了啊啊.. 其实仔细一想也是那么回事.欧拉回路是遍历所有边一次又回到起点的回路.双向图只要每个点度数 ...

随机推荐

  1. 在springMVC的controller层获取view层的参数的方式

    方法一:request.getParameter("name") 方法二:注解@RequestParam @RequestMapping("testRequestPara ...

  2. 二叉树计数(codevs 3112)

    题目描述 Description 一个有n个结点的二叉树总共有多少种形态 输入描述 Input Description 读入一个正整数n 输出描述 Output Description 输出一个正整数 ...

  3. stm32——NFC芯片--PN532的使用

    stm32——NFC芯片--PN532的使用 一.NFC简介 NFC(Near Field Communication)近场通信,是一种短距高频的无线电技术,在13.56MHz频率运行于20厘米距离内 ...

  4. Oracle读写分离架构

    读写分离是架构分布式系统的一个重要思想.不少系统整体处理能力并不能同业务的增长保持同步,因此势必会带来瓶颈,单纯的升级硬件并不能一劳永逸.针对业务类型特点,需要从架构模式上进行一系列的调整,比如业务模 ...

  5. myeclipse 8.5 注册码

    刚才启动突然发现MyEclipse原来是收费的...汗一把,到弹出注册框我才知道.....老天啊我活的该有多窝囊.. 弹框很烦人,我一个穷书生既想继续学习又囊中羞涩无力购买,只好用盗版了(找个理由辩解 ...

  6. PostgreSQL中COUNT的各条件下(1亿条数据)例子

    test=# insert into tbl_time1 select generate_series(1,100000000),clock_timestamp(),now(); INSERT 0 1 ...

  7. FastPolice项目总结

    This is the final homework for spatial information Mobile Service Lesson.It generally inclusived the ...

  8. GBDT原理实例演示 2

        一开始我们设定F(x)也就是每个样本的预测值是0(也可以做一定的随机化) Scores = { 0, 0, 0, 0, 0, 0, 0, 0}     那么我们先计算当前情况下的梯度值     ...

  9. 跳跃表Skip List的原理和实现

    >>二分查找和AVL树查找 二分查找要求元素可以随机访问,所以决定了需要把元素存储在连续内存.这样查找确实很快,但是插入和删除元素的时候,为了保证元素的有序性,就需要大量的移动元素了.如果 ...

  10. Delphi线程的终止

    当线程对象的Execute()执行完毕,我们就认为此线程终止了.这时候,它会调用Delphi的一个标准例程EndThread(),这个例程再调用API函数ExitThread().由ExitThrea ...