混合图的欧拉回路定向问题。
顺便瞎说几句,有向图定欧拉回路的充要条件是每个点入度等于出度,并且图联通。无向图的话只要联通无奇点即可。
欧拉路径的确定应该是无向图联通且奇点数0个或2个,有向图忘了,好像复杂一点,这个真考到就暴力瞎搜吧。
既然每个点的度数都定了,又入度等于出度,那两者对半分,在二分图里左向右连上原图的边,左点集与s连容量为待补充的出度,右点集反之。这样如果我真可以定下来的话,就会有左边所有连边都满流。所以跑最大流看能不能到满流(就是差的总出度)即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 typedef long long ll; 8 template<typename T>inline char MIN(T&A,T B){return A<B?A=B,1:0;} 9 template<typename T>inline char MAX(T&A,T B){return A>B?A=B,1:0;} 10 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 11 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 12 template<typename T>inline T read(T&x){ 13 x=0;char c;while(!isdigit(c=getchar()))if(isalpha(c))return x=(int)c; 14 while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();return x; 15 } 16 const int N=200+7,M=3000+7,INF=0x3f3f3f3f; 17 int w[M<<1],v[M<<1],Next[M<<1],Head[N<<1],cur[N<<1],dis[N<<1],tot,s,t,n,m; 18 inline void Addedge(int x,int y,int z){ 19 v[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z; 20 v[++tot]=x,Next[tot]=Head[y],Head[y]=tot,w[tot]=0; 21 } 22 #define y v[j] 23 inline char bfs(){ 24 queue<int> q;q.push(s),memset(dis,0,sizeof dis),dis[s]=1; 25 for(register int i=1;i<=(n<<1)+2;++i)cur[i]=Head[i]; 26 while(!q.empty()){ 27 int x=q.front();q.pop(); 28 for(register int j=Head[x];j;j=Next[j])if(w[j]&&!dis[y]){ 29 dis[y]=dis[x]+1,q.push(y); 30 if(y==t)return 1; 31 } 32 } 33 return 0; 34 } 35 int dinic(int x,int flow){ 36 if(!flow||x==t)return flow; 37 int rest=flow,k; 38 for(register int j=cur[x];j&&rest;cur[x]=j,j=Next[j])if(w[j]&&dis[y]==dis[x]+1){ 39 if(!(k=dinic(y,_min(rest,w[j]))))dis[y]=0; 40 rest-=k,w[j]-=k,w[j^1]+=k; 41 } 42 return flow-rest; 43 } 44 #undef y 45 int in[N],out[N],cnt[N]; 46 int x,y,z,T,p,tmp,ans,sigma; 47 inline void inc(int x,int y){++out[x],++in[y];} 48 49 int main(){//freopen("tmp.in","r",stdin);freopen("tmp.out","w",stdout); 50 read(T);while(T--){ 51 read(n),read(m);s=(n<<1)+1,t=(n<<1)+2,p=tot=1,sigma=ans=0; 52 memset(Head,0,sizeof Head),memset(in,0,sizeof in),memset(out,0,sizeof out),memset(cnt,0,sizeof cnt); 53 for(register int i=1;i<=m;++i){ 54 read(x),read(y),read(z);if(x==y)continue; 55 z?inc(x,y):(Addedge(x,y+n,1),Addedge(y,x+n,1));++cnt[x],++cnt[y]; 56 } 57 for(register int i=1;i<=n;++i)if(cnt[i]&1){ 58 printf("impossible ");p=0;break; 59 } 60 else{ 61 tmp=cnt[i]>>1;if(tmp<in[i]||tmp<out[i]){printf("impossible ");p=0;break;} 62 Addedge(s,i,tmp-out[i]),Addedge(i+n,t,tmp-in[i]),sigma+=tmp-out[i]; 63 } 64 if(p){ 65 while(bfs())ans+=dinic(s,INF); 66 if(ans==sigma)printf("possible "); 67 else printf("impossible "); 68 } 69 } 70 return 0; 71 }