http://poj.org/problem?id=1637
转自kuangbin巨巨
http://www.cnblogs.com/kuangbin/p/3537525.html
一个混合图,既含无向边又含有向边
对无向边任取一个方向,将混合图变为有向图,转变为有向图后,根据有向图欧拉通路/回路的充要条件,进行判断
1.有向图是欧拉图当且仅当是强连通的且每个顶点的入度等于出度
2.有向图是半欧拉图当且仅当是单向连通的且恰有两个奇度顶点,其中一个顶点的入度比出度大1,另一个顶点的出度比入度大1
记D[i]=out[i]-in[i]
1.如果D[i]>0,则source与i连边,cap为D[i]/2;
2.如果D[i]<0,则i与sink连边,cap为D[i]/2;
求一次最大流,如果满流,则存在欧拉回路/通路
//176K 16MS C++
#include<cstdio>
#include<cstring>
const int MAXN=220;
const int MAXM=4000;
const int INF=0x3f3f3f3f;
int n,s,t,N;//输入的顶点数,源点,汇点,总顶点数
int m;
int in[MAXN],out[MAXN];
struct Edge{
int to,next,cap,flow;
}edge[MAXM];
int head[MAXN],tot,gap[MAXN],d[MAXN],cur[MAXN],que[MAXN],p[MAXN];
void init(){
tot=0;
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
}
void addedge(int u,int v,int c){
edge[tot].to=v;
edge[tot].cap=c;
edge[tot].flow=0;
edge[tot].next=head[u];
head[u]=tot++;
edge[tot].to=u;
edge[tot].cap=0;
edge[tot].flow=0;
edge[tot].next=head[v];
head[v]=tot++;
}
void BFS(){
memset(d,-1,sizeof(d));
memset(gap,0,sizeof(gap));
gap[0]=1;
int front=0,rear=0;
d[t]=0;
que[rear++]=t;
while(front!=rear){
int u=que[front++];
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(d[v]!=-1) continue;
que[rear++]=v;
d[v]=d[u]+1;
gap[d[v]]++;
}
}
}
int isap(){
BFS();
memcpy(cur,head,sizeof(head));
int top=0,x=s,flow=0;
while(d[s]<N){
if(x==t){
int Min=INF,inser;
for(int i=0;i<top;++i){
if(Min>edge[p[i]].cap-edge[p[i]].flow){
Min=edge[p[i]].cap-edge[p[i]].flow;
inser=i;
}
}
for(int i=0;i<top;++i){
edge[p[i]].flow+=Min;
edge[p[i]^1].flow-=Min;
}
flow+=Min;
top=inser;
x=edge[p[top]^1].to;
continue;
}
int ok=0;
for(int i=cur[x];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&d[v]+1==d[x]){
ok=1;
cur[x]=i;
p[top++]=i;
x=edge[i].to;
break;
}
}
if(!ok){
int Min=n+n+2;
for(int i=head[x];i!=-1;i=edge[i].next){
if(edge[i].cap>edge[i].flow&&d[edge[i].to]<Min){
Min=d[edge[i].to];
cur[x]=i;
}
}
if(--gap[d[x]]==0) break;
gap[d[x]=Min+1]++;
if(x!=s) x=edge[p[--top]^1].to;
}
}
return flow;
}
void Build_graph(){
s=0,t=n+1,N=t+1;
bool flag=true;
for(int i=1;flag&&i<=n;++i){
if(out[i]-in[i]>0) addedge(s,i,(out[i]-in[i])/2);
else if(in[i]-out[i]>0) addedge(i,t,(in[i]-out[i])/2);
if((out[i]-in[i])&1) flag=false;
}
if(!flag) printf("impossible\n");
else{
isap();
for(int i=head[0];flag&&i!=-1;i=edge[i].next){
if(edge[i].cap>edge[i].flow) flag=false;
}
if(!flag) printf("impossible\n");
else printf("possible\n");
}
}
int main()
{
int T,u,v,w;
scanf("%d",&T);
while(T--){
init();
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i){
scanf("%d%d%d",&u,&v,&w);
in[v]++,out[u]++;
if(w==0) addedge(u,v,1);
}
Build_graph();
}
return 0;
}