POJ 1637 - Sightseeing tour 判断混合图是否是欧拉回路(最大流)
来源:互联网 发布:小型图书馆源码 编辑:程序博客网 时间:2024/04/18 19:17
题意:
给一个图..有些边是有向的...有些边是无向的...问能否有一条路径..从某点出发..又回到该点..并且所有的边经过exaclty一次...
题解
这题就是判断混合图欧拉回路的裸题....解法是先任意将每个无向边定向..然后来调整...看能否满足有向图欧拉回路的条件(所有点入度=出度)...
具体的...在把所有无向边定向后..先看每个点入度和出度之差..若有一个点其为奇数..则说明impossible..因为就算后面调整..调整一个边的方向..两头的点入度出度之差的变化必然为偶数...所以若为奇数..无论如何调整都无法使其变成0...然后就要看能否经过调整变成一个欧拉图了...参考了别人的建图...所有无向边定向后起点到终点连一条容量为1的边...然后设一个超级源点,向所有所有出度多了点做边..容量为其多了的边数/2(因为每次改变边..出度-1,入度+1..之差变化2)...所有入度多了的点往一个超级汇点做边..容量为其多了的边数/2...跑最大流...然后看和超级源点连得边是否容量都空了..与超级汇点连得边是否容量都空了...如果都空了..则说明是可以构造成欧拉图的..
构边理由..1、是无向边两点间容量为1的边..代表这个无向边至多改变方向一次...
2、超级源点和超级汇点的边代表连着的这些点要让入度出度之差为0...所以要从左侧出度多的..调整到右侧入度多的..如果这些边都为0..就说明了可以让所有的点入度=出度...
总结此类模型的特点: 整个对象可以分成两个集合..并且其中一个集合是要从另一个集合中获取资源..而另一个集合也必须要释放资源...使得两个集合的资源都正好...
Program:
#include<iostream>#include<algorithm>#include<stdio.h>#include<string.h>#include<math.h>#include<queue>#define MAXN 3005#define MAXM 500005#define oo 1000000007#define ll long longusing namespace std;int d[MAXN];struct Dinic{ struct node { int x,y,c,next; }line[MAXM]; int Lnum,_next[MAXN],dis[MAXN]; void initial(int n) { for (int i=0;i<=n;i++) _next[i]=-1; Lnum=-1; } void addline(int x,int y,int c) { line[++Lnum].next=_next[x],_next[x]=Lnum; line[Lnum].x=x,line[Lnum].y=y,line[Lnum].c=c; line[++Lnum].next=_next[y],_next[y]=Lnum; line[Lnum].x=y,line[Lnum].y=x,line[Lnum].c=0; } bool BFS(int s,int e) { queue<int> Q; while (!Q.empty()) Q.pop(); memset(dis,0,sizeof(dis)); dis[s]=1; Q.push(s); while (!Q.empty()) { int h,k; h=Q.front(),Q.pop(); if (h==e) return dis[e]; for (k=_next[h];k!=-1;k=line[k].next) if (line[k].c && !dis[line[k].y]) dis[line[k].y]=dis[h]+1,Q.push(line[k].y); } return false; } int dfs(int x,int flow,int e) { if (x==e) return flow; int temp,cost=0; for (int k=_next[x];k!=-1;k=line[k].next) if (line[k].c && dis[line[k].y]==dis[x]+1) { temp=dfs(line[k].y,min(flow-cost,line[k].c),e); if (temp) { line[k].c-=temp,line[k^1].c+=temp; cost+=temp; if (flow==cost) return cost; }else dis[line[k].y]=-1; } return cost; } int MaxFlow(int s,int e) { int MaxFlow=0; while (BFS(s,e)) MaxFlow+=dfs(s,oo,e); return MaxFlow; }}T;bool legal(int n){ int i; for (i=1;i<=n;i++) if (d[i]%2) return false; return true;}int main() { int n,m,cases,x,y,c,s,e,sum; scanf("%d",&cases); while (cases--) { scanf("%d%d",&n,&m); s=n+1,e=s+1,sum=0; T.initial(e); memset(d,0,sizeof(d)); while (m--) { scanf("%d%d%d",&x,&y,&c); d[x]--,d[y]++; if (!c) T.addline(x,y,1); } if (!legal(n)) { printf("impossible\n"); continue; } for (int i=1;i<=n;i++) { d[i]/=2; if (d[i]<0) T.addline(s,i,-d[i]); if (d[i]>0) T.addline(i,e,d[i]); sum+=abs(d[i]); } sum>>=1; if (T.MaxFlow(s,e)==sum) printf("possible\n"); else printf("impossible\n"); } return 0; }
- POJ 1637 - Sightseeing tour 判断混合图是否是欧拉回路(最大流)
- 【POJ 1637】Sightseeing tour 混合图欧拉回路 最大流
- POJ 1637 Sightseeing tour (混合图欧拉回路,网络最大流)
- 【最大流+混合图欧拉回路】POJ-1637 Sightseeing tour
- POJ 1637 Sightseeing tour 混合图欧拉回路 最大流
- poj--1637--Sightseeing tour(网络流,最大流判断混合图是否存在欧拉图)
- POJ 637 Sightseeing tour 混合欧拉回路 最大流
- POJ 1637 Sightseeing tour 混合路欧拉回路判断
- poj 1673(Sightseeing tour)(判断混合图是否存在欧拉回路)
- POJ 1637 Sightseeing tour (混合图欧拉回路)
- poj 1637 Sightseeing tour(混合图欧拉回路)
- poj -- 1637 Sightseeing tour(混合图欧拉回路)
- [POJ 1637]Sightseeing tour[混合图欧拉回路]
- POJ 1637:Sightseeing tour 混合图欧拉回路
- poj 1637 Sightseeing tour 【网络流 求解混合欧拉回路是否存在】
- POJ 1637 Sightseeing tour(混合欧拉回路,网络流)
- POJ 1637 Sightseeing tour (混合图的欧拉回路)
- POJ 1637 Sightseeing tour(混合图的欧拉回路)
- N个筛子,掷出M值的可能性
- 2013.8.25
- wikioi p1166 矩阵取数游戏
- 烟台大学acm暑期集训总结
- 谷歌笔试题-背包问题
- POJ 1637 - Sightseeing tour 判断混合图是否是欧拉回路(最大流)
- Hibernate 4 Util
- 重载_static_new
- wikioi p1010 过河卒
- vi、akw和sed总结
- 原来NSArray装的也是强类型元素,一直以为是弱类型.
- 树状数组合集
- 匿名内部类抽象实现枚举
- wikioi p1219 骑士游历