雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

混合边的欧拉路径——poj1637 最大流

Posted on 2012-03-22 21:51  huhuuu  阅读(675)  评论(0编辑  收藏  举报

http://poj.org/problem?id=1637

题意:混合图欧拉回路

一开始想到是否可以用欧拉回路做,可是一想a->b ,a<->b可以同时并且多次存在时,不可行
 

构图:有向边忽略,无向边任意定向。统计每个点的出入度(有向边当无向边)。

对于任意一个点,若有出入度之差为奇数则不可能存在欧拉路。

记|出度-入度|=K。

对于出度大于入度的点从S向I连容量为K/2的边,对于出度小于入度的点从I向T连容量为K/2的边。

原来的无向边,任意定向,从X向Y连容量1的边。

求最大流,判每条从S流出的边的流量和all是否等于最大流,是则存在欧拉路否则不存在。

 

注意点:会有重边出现!而且重边也要走的

View Code
#include<stdio.h>
#include<string.h>
const int MAXN=309;
const int inf=1000000000;

int map[MAXN][MAXN];
int doub[MAXN][MAXN];
int du[MAXN];

int max_flow(int n,int mat[][MAXN],int source,int sink)
{
int v[MAXN],c[MAXN],p[MAXN],ret=0,i,j;
for(;;){
for(i=0;i<n;i++)
v[i]=c[i]=0;
for(c[source]=inf;;){
for(j=-1,i=0;i<n;i++)
if(!v[i]&&c[i]&&(j==-1||c[i]>c[j]))
j=i;
if(j<0)return ret;
if(j==sink)break;
for(v[j]=1,i=0;i<n;i++)
if(mat[j][i]>c[i]&&c[j]>c[i])
c[i]=mat[j][i]<c[j]?mat[j][i]:c[j],p[i]=j;
}
for(ret+=j=c[i=sink];i!=source;i=p[i])
mat[p[i]][i]-=j,mat[i][p[i]]+=j;
}
return ret;
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n,m;
memset(map,0,sizeof(map));
memset(doub,0,sizeof(doub));
memset(du,0,sizeof(doub));

scanf("%d%d",&n,&m);
int i,j,a,b,c;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&c);
map[a][b]++;
doub[a][b]+=c^1;//注意无向边的容量作为1加到容量网络
du[a]++;//会有重边出现!
du[b]--;
}

int ok=1;
for(i=1;i<=n;i++)
{
if(du[i]%2!=0)
{
ok=0;
break;
}
}
if(ok==0)
{
printf("impossible\n");
continue;
}

int all=0;
for(i=1;i<=n;i++)
{
if(du[i]>0)
{
doub[0][i]=du[i]/2;
all+=du[i]/2;
}
else if(du[i]<0)
{
doub[i][n+1]=-du[i]/2;
}
}

if(max_flow(n+2,doub,0,n+1)==all)
{
printf("possible\n");
}
else
printf("impossible\n");
}

return 0;
}


一个速度比较快的代码

View Code
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <algorithm>
#define MAX 205
using namespace std;
int pre[MAX],n;
int ind[MAX],outd[MAX];
int lev[MAX];

int min(int a,int b)
{
if(a<b)return a;
else return b;
}

typedef struct MAP{
int cap,to;
int next;
}MAP;
MAP node[3000];
int head[MAX];
int cou;
void init()
{
cou = 2;
memset(node,'/0',sizeof(node));
memset(head,-1,sizeof(head));
memset(ind,0,sizeof(ind));
memset(outd,0,sizeof(outd));
for(int i=1; i<=n; i++)
pre[i] = i;
}
int find(int x)
{
while( x != pre[x] )
x = pre[x];
return x;
}
void Union(int x,int y)
{
int a = find(x);
int b = find(y);
if( a == b )
return ;
int p = min(a,b);
pre[a] = pre[b] = pre[x] = pre[y] = p;
}
int check()
{
for(int i=1; i<=n; i++)
if( find(i) != 1 )
return 0;
return 1;
}
void Add(int u,int v,int cap)
{
node[cou].to = v;
node[cou].cap = cap;
node[cou].next = head[u];
head[u] = cou++;

node[cou].to = u;
node[cou].cap = 0;
node[cou].next = head[v];
head[v] = cou++;
}
queue<int> q;
int BFS(int s,int t)
{
int p,u,v,cap;
memset(lev,-1,sizeof(lev));
q.push(s);
lev[s] = 0;
while( !q.empty() )
{
u = q.front();
q.pop();
p = head[u];
while( p != -1 )
{
v = node[p].to;
cap = node[p].cap;
if( cap > 0 && lev[v] == -1 )
{
lev[v] = lev[u] + 1;
q.push(v);
}
p = node[p].next;
}
}
return lev[t] != -1;
}
int Dinic(int k,int sum,int s,int t)
{
int i,a,os;
if( k == t )
return sum;
os = sum;
int p = head[k];
while( p != -1 && sum )
{
int to = node[p].to;
int cap = node[p].cap;
if( lev[to] == lev[k] + 1 && cap > 0 )
{
a = Dinic(to,min(sum,cap),s,t);
node[p^1].cap += a;
node[p].cap -= a;
sum -= a;
}
p = node[p].next;
}
return os - sum;
}
int main()
{
int m,from,to,s;
int ncases;
scanf("%d",&ncases);
while( ncases-- )
{
scanf("%d%d",&n,&m);
init();
while( m-- )
{
scanf("%d%d%d",&from,&to,&s);
if( from == to )
continue;
ind[to]++;
outd[from]++;
Union(from,to);
if( s != 1 )
Add(from,to,1);
}
if( !check() )
{
printf("impossible/n");
continue;
}
int flag = 1;
int sum = 0;
for(int i=1; i<=n; i++)
{
outd[i] -= ind[i];
if( outd[i] % 2 == 1 )
{
flag = 0;
break;
}
outd[i] /= 2;
if( outd[i] > 0 )
{
Add(0,i,outd[i]);
sum += outd[i];
}
else
Add(i,n+1,-outd[i]);
}
if( !flag )
{
printf("impossible\n");
continue;
}
int ans = 0;
while( BFS(0,n+1) )
ans += Dinic(0,INT_MAX,0,n+1);
if( ans == sum )
printf("possible\n");
else
printf("impossible\n");
}
return 0;
}