1. 程式人生 > >poj 1637 Sightseeing tour【最大流+歐拉路】

poj 1637 Sightseeing tour【最大流+歐拉路】

tps spa tour ble 條件 ons emp possible !=

參考:https://www.cnblogs.com/kuangbin/p/3537525.html
這篇講的挺好的
首先分清歐拉路和歐拉環:
歐拉路:圖中經過每條邊一次且僅一次的路徑,要求只有兩個點的出入度之差為奇數,這兩個點即為歐拉路的起點和終點
歐拉環:圖中經過每條邊一次且僅一次的環,要求全部點的出入度之差為偶數
這道題中要判定的是歐拉路。首先看是否滿足“只有兩個點的出入度之差為奇數”這個條件,可以發現盡管有沒有定向的邊,但是出入的之差的奇偶是不變的;假設一條從i出發的邊變向為到達i,那麽點i的入度+1出度-1,差的奇偶性不變。
判定可以用網絡流來做:s向所有差>0的點連流量為差/2的邊,所有差<0的邊向t連流量為差/2的邊。對於原有的雙向邊隨便定個向,連流量為1的邊,意味著只能改一次方向。
然後跑最大流,最後看是否所有與s相連的邊都滿流。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=100005,inf=1e9;
int T,n,m,h[N],cnt,le[N],in[N],out[N],s,t;
struct qwe
{
    int ne,to,v;
}e[N];
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>‘9‘||p<‘0‘)
    {
        if
(p==‘-‘) f=-1; p=getchar(); } while(p>=‘0‘&&p<=‘9‘) { r=r*10+p-48; p=getchar(); } return r*f; } void add(int u,int v,int w) { cnt++; e[cnt].ne=h[u]; e[cnt].to=v; e[cnt].v=w; h[u]=cnt; } void ins(int u,int v,int w) { add(u,v,w); add(v,u,0
); } int bfs() { queue<int>q; memset(le,0,sizeof(le)); le[s]=1; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=h[u];i;i=e[i].ne) if(!le[e[i].to]&&e[i].v>0) { le[e[i].to]=le[u]+1; q.push(e[i].to); } } return le[t]; } int dfs(int u,int f) { if(!f||u==t) return f; int us=0; for(int i=h[u];i;i=e[i].ne) if(le[u]+1==le[e[i].to]&&e[i].v>0) { int t=dfs(e[i].to,min(e[i].v,f-us)); e[i].v-=t; e[i^1].v+=t; us+=t; } if(!us) le[u]=0; return us; } void dinic() { int re=0; while(bfs()) dfs(s,inf); } int main() { T=read(); while(T--) { n=read(),m=read(); s=0,t=n+1; cnt=1; memset(h,0,sizeof(h)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); for(int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); out[x]++,in[y]++; if(z==0) ins(x,y,1); } bool f=1; for(int i=1;i<=n;i++) { if((out[i]-in[i])%2==1) { f=0; break; } if(out[i]-in[i]>0) ins(s,i,(out[i]-in[i])/2); else if(out[i]-in[i]<0) ins(i,t,(in[i]-out[i])/2); } if(!f) { puts("impossible"); continue; } dinic(); for(int i=h[s];i;i=e[i].ne) if(e[i].v!=0) { f=0; break; } if(!f) puts("impossible"); else puts("possible"); } return 0; }

poj 1637 Sightseeing tour【最大流+歐拉路】