混合图的欧拉回路问题。
混合图就是边集中有有向边和无向边同时存在。这时候需要用网络流建模求解。
建模:
把该图的无向边随便定向,计算每个点的入度和出度。如果有某个点出入度之差为奇数,那么肯定不存在欧拉回路。 因为欧拉回路要求每点入度 = 出度,也就是总度数为偶数,存在奇数度点必不能有欧拉回路。
好了,现在每个点入度和出度之差均为偶数。那么将这个偶数除以2,得x。也就是说,对于每一个点,只要将x条边改变方向(入>出就是变入,出>入就是变出),就能保证出 = 入。如果每个点都是出 = 入,那么很明显,该图就存在欧拉回路。
现在的问题就变成了:我该改变哪些边,可以让每个点出 = 入?构造网络流模型。
首先,有向边是不能改变方向的,要之无用,删。一开始不是把无向边定向了吗?定的是什么向,就把网络构建成什么样,边长容量上限1。另新建s和t。对于入 > 出的点u,连接边(u, t)、容量为x,对于出 > 入的点v,连接边(s, v),容量为x(注意对不同的点x不同)。
之后,察看从S发出的所有边是否满流。有就是能有欧拉回路,没有就是没有。欧拉回路是哪个?察看流值分配,将所有流量非 0(上限是1,流值不是0就是1)的边反向,就能得到每点入度 = 出度的欧拉图。
由于是满流,所以每个入 > 出的点,都有x条边进来,将这些进来的边反向,OK,入 = 出了。对于出 > 入的点亦然。那么,没和s、t连接的点怎么办?和s连接的条件是出 > 入,和t连接的条件是入 > 出,那么这个既没和s也没和t连接的点,自然早在开始就已经满足入 = 出了。那么在网络流过程中,这些点属于“中间点”。我们知道中间点流量不允许有累积的,这样,进去多少就出来多少,反向之后,自然仍保持平衡。
所以,就这样,混合图欧拉回路问题,解了。
#define MIN INT_MIN
#define MAX INT_MAX
#define N 220
int min(int a,int b){return a>b?b:a;}
int g[N][N];
int du[N];
int res[N];
int pre[N];
int f[N][N];
int n;
bool EK(int s,int t,int cnt){
int i,j;
queue<int> qq;
memset(f,0,sizeof(f));
int ans=0;
while(1){
memset(res,0,sizeof(res));
res[s] = MAX;
pre[s] = -1;
qq.push(s);
while(!qq.empty()){
int u = qq.front();
qq.pop();
for(int v=s;v<=t;v++){
if(!res[v] && f[u][v] < g[u][v]){
qq.push(v);
pre[v] = u;
res[v] = min(res[u] , g[u][v] - f[u][v]);
}
}
}
if(!res[t])break;
int k = t;
while(pre[k] != -1){
f[pre[k]][k] += res[t];
f[k][pre[k]] -= res[t];
k = pre[k];
}
}
for(i=1;i<=n;i++){
ans+=f[0][i];
}
return ans==cnt;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
int m;
scanf("%d%d",&n,&m);
int i,j;
memset(du,0,sizeof(du));
memset(g,0,sizeof(g));
while(m--){
int a,b,type;
scanf("%d%d%d",&a,&b,&type);
du[a]++;
du[b]--;
if(!type){
g[a][b]++;
}
}
bool ok = 1;
for(i=1;i<=n;i++){
if(abs(du[i]) % 2 == 1){//若点的出度与入度差为奇数就一定不存在欧拉回路
ok = 0;
break;
} else {
du[i] = du[i]/2;//网络中每条边的权值都为出度与入度差的一半
}
}
if(!ok){
puts("impossible");
continue;
}
int cnt=0;
for(i=1;i<=n;i++){
if(du[i]<0){//出<入,连至汇点
g[i][n+1] = abs(du[i]);
} else if(du[i]>0){//出>入,连至源点
g[0][i] = du[i];
cnt+=du[i];//cnt是验证是否满流
}
}
if(EK(0,n+1,cnt)){
puts("possible");
} else puts("impossible");
}
return 0;
}