POJ 1637 混合图欧拉回路判断 最大流模板

来源:互联网 发布:oracle 删数据 sql 编辑:程序博客网 时间:2024/06/08 06:03

题意 给你一个混合图(有向边+无向边),判断是否存在欧拉回路

思路 设d(i) = 出度(i) - 入度(i)。无向边随意定向,先并查集判连通,判di是否都为偶数,不是则不行。

建图,加入s,t两点,对di>0的,s->i建边,最大流量为di/2,对di<0,i->t建边,最大流量为-di/2。把随意定向的无向边,加入图中,最大流量为1.跑最大流,如果最后从s出的边都满流,则有欧拉回路。把那些流量为1的边反向即可加入原图中即可完成无向边的定向。

注意:满流的判断,就用一条边一条边的去看~别瞎用什么别的判别法~

#include <iostream>#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <algorithm>using namespace std;const int maxn = 202;const int maxm = 1003;const int inf = 0x3f3f3f3f;int n,m;int g[maxn][maxn][2];int d[maxn];struct EdmondsKarp{//用到外部变量maxn,maxm,具体使用不非得按照模板 int n,m;int g[maxn][maxn];int flow[maxn];int path[maxn];queue<int> q; void init(int nn=0){n = nn;memset(g,0,sizeof(g));memset(flow,0,sizeof(flow));memset(path,-1,sizeof(path));}void addOne(int u,int v,int yuan){g[u][v] += yuan;m += 2; }int bfs(int s,int t){int i;memset(path,-1,sizeof(path));flow[s] = inf;//如果不加这句话,bfs内部就要一共三个判断 path[s] = s; q.push(s);while(q.size()>0){int tmp = q.front();q.pop();//这里i从0开始还是1开始,视情况而定 for(i=0;i<n;i++){if(g[tmp][i]>0 && path[i]==-1){flow[i] = min(g[tmp][i],flow[tmp]);path[i] = tmp;q.push(i);if(i==t){break;}}}if(path[t] != -1)break;}while(q.size()>0)q.pop();if(path[t] == -1)return 0;elsereturn flow[t];}int go(int s,int t){int ret = 0;while(bfs(s,t)){int now = path[t];int pre = t;ret += flow[t];while(pre != s){g[now][pre] -= flow[t];g[pre][now] += flow[t];pre = now;now = path[now];}}return ret;}}edk;int fa[maxn];int find(int x){if(fa[x] == x)return x;elsereturn fa[x] = find(fa[x]);}void unin(int x,int y){x = find(x);y = find(y);if(x==y)return;fa[x] = y;}void addEdge(){scanf("%d%d",&n,&m);memset(g,0,sizeof(g));memset(d,0,sizeof(d));for(int i=1;i<=n;i++)fa[i] = i;for(int i=0;i<m;i++){int u,v,b;scanf("%d%d%d",&u,&v,&b);if(b==1)g[u][v][1]++;elseg[u][v][0]++;//出度减入度 d[u]++;d[v]--;unin(u,v);}}void create(){edk.init(n+2);for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(g[i][j][0])edk.addOne(i,j,g[i][j][0]);}}for(int i=1;i<=n;i++){if(d[i] > 0){edk.addOne(0,i,d[i]/2);}else if(d[i] < 0){edk.addOne(i,n+1,-d[i]/2);}}}bool judge(){for(int i=2;i<=n;i++){if(find(i) != find(i-1))return false;}for(int i=1;i<=n;i++){if(d[i] % 2 != 0)return false;}return 1;}int main(){int T;cin>>T;while(T--){addEdge();if(judge() == 0){puts("impossible");continue;}create();edk.go(0,n+1);int sum = 0;int i = 1;for(i=1;i<=n;i++){if(d[i] > 0){if(edk.g[0][i] > 0)break;}}if(i == n+1)puts("possible");elseputs("impossible");}return 0;}


0 0
原创粉丝点击