混合图的欧拉回路,看到这道题觉得好难啊.....
去嫖了黄学长的题解
首先考虑该图是否合法,即考虑出入度的问题,将无向边任取方向,设d[x]等于出度-入度,判断d[x]是否都为偶数
d[x]/2即为连接每个点的边需要反向的数量
若大于0,则从源点连边,若小于0,则向汇点连边
判断最大流是否等于∑ d[x]/2
r[i]=head[i]; q[qr=1]=S;dep[S]=0; for(int ql=1;ql<=qr;ql++) { int u=q[ql]; for(int i=head[u],v;i;i=e[i].next) { if(e[i].w && dep[v=e[i].to]==-1) { dep[v]=dep[u]+1; q[++qr]=v; if(v==T) return 1; } } } return 0; } int dinic(int u,int flow) { if(u==T) return flow; int ret=0,delta,v; for(int i=head[u];i;i=e[i].next) { if(e[i].w && dep[v=e[i].to]==dep[u]+1) { delta=dinic(v,min(e[i].w,flow-ret)); if(delta) { e[i].w-=delta; e[i^1].w+=delta; ret+=delta; if(ret==flow) break; } } } if(ret!=flow) dep[u]=-1; return ret; } int Case,tot; int d[N],n,m; bool check() { for(int i=1;i<=n;i++) { if(d[i]%2!=0) return 1; } return 0; } int main() { scanf("%d",&Case); while(Case--) { memset(head,0,sizeof(head)); ecnt=1;memset(d,0,sizeof(d)); tot=0; scanf("%d%d",&n,&m); S=n+1;T=S+1; for(int i=1,u,v,p;i<=m;i++) { scanf("%d%d%d",&u,&v,&p); d[u]++;d[v]--; if(!p) add(u,v,1); } if(check()) { puts("impossible"); continue; } for(int i=1;i<=n;i++) { if(d[i]<0) add(i,T,-d[i]/2); if(d[i]>0) add(S,i,d[i]/2),tot+=d[i]/2; } int ans=0; while(bfs()) ans+=dinic(S,inf); //printf("%d\n",ans); if(ans!=tot) puts("impossible"); else puts("possible"); } return 0; }