混合图的欧拉回路,看到这道题觉得好难啊.....

去嫖了黄学长的题解

首先考虑该图是否合法,即考虑出入度的问题,将无向边任取方向,设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;
}