//网络流判定混合图欧拉回路 //通过网络流使得各点的出入度相同则possible,否则impossible //残留网络的权值为可改变方向的次数,即n个双向边则有n次 //Time:157Ms Memory:348K #include <iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> using namespace std; #define MAXN 205 #define INF 0x3f3f3f3f int n,m; int s,t; int dif[MAXN]; int res[MAXN][MAXN]; //残留网络-代表可变方向数 int pre[MAXN]; bool bfs() { memset(pre,-1,sizeof(pre)); queue<int> q; q.push(s); pre[s] = 0; while(!q.empty()){ int cur = q.front(); q.pop(); for(int i = 1; i <= t; i++) { if(pre[i] == -1 && res[cur][i]) { pre[i] = cur; if(i == t) return true; q.push(i); } } } return false; } int EK() { int maxFlow = 0; while(bfs()){ int mind = INF; for(int i = t; i != s; i = pre[i]) mind = min(mind, res[pre[i]][i]); for(int i = t; i != s; i = pre[i]) { res[pre[i]][i] -= mind; res[i][pre[i]] += mind; } maxFlow += mind; } return maxFlow; } int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); while(T--){ memset(dif,0,sizeof(dif)); memset(res,0,sizeof(res)); scanf("%d%d", &n, &m); int total = 0; s = 0; t = n+1; for(int i = 0; i < m; i++) { int u,v,t; scanf("%d%d%d", &u,&v,&t); dif[u]++; dif[v]--; if(t == 0) res[u][v] += 1; //重边则可变方向+1 } bool flag = true; for(int i = 1; i <= n; i++) { if(dif[i] > 0) { //出度多-通过源点给予奇数入度 res[s][i] = dif[i]/2; total += dif[i]/2; } if(dif[i] < 0) res[i][t] = -dif[i]/2; //入度多-通过汇点给予奇数出度 if(abs(dif[i]) % 2 == 1) { flag = false; break; } } (flag && EK() == total)? printf("possible\n"): printf("impossible\n"); } return 0; }
时间: 2024-10-03 22:37:51