poj 1637 Sightseeing tour(混合图欧拉回路)

来源:互联网 发布:煎饼侠 知乎 编辑:程序博客网 时间:2024/05/01 17:40

           混合图判断欧拉回路需要转换为网络流问题,首先把无向边当作有向边,然后对于每个点,如果存在点的入度和出度之差为奇数的话,就肯定不存在欧拉回路。对于都是偶数的情况,我们需要对于入度大于出度的点i,我们需要加一条源点到点i的边,容量为出入度差值的一半(因为只需要改变一半边的方向就可以使得点i满足入度等于出度),对于出度大于入度的边,需要加一条点i到汇点的边,容量为出入度差值的一半。然后对于原来的无向边,需要把假定方向的反向边数作为容量加到新图中,作为可以修改方向的上界。这样的话如果新图最大流等于需要的流量,就说明可以满足。如果需要输出修改方案的话也是比较简单的。

#include<algorithm>#include<iostream>#include<cstring>#include<vector>#include<cstdio>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#define MP make_pair#define LL long long#define CLR(a, b) memset(a, b, sizeof(a))using namespace std;const int maxn = 220;const int INF = 0x3f3f3f3f;int mp[maxn][maxn];int in[maxn], out[maxn];struct Edge{    int from, to, cap, flow;    Edge(){}    Edge(int from, int to, int cap, int flow)        :from(from), to(to), cap(cap), flow(flow){}};struct ISAP{    int n, m, s, t;    vector<Edge> edges;    vector<int> G[maxn];   // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号    bool vis[maxn];        // BFS使用    int d[maxn];           // 从起点到i的距离    int cur[maxn];        // 当前弧指针    int p[maxn];          // 可增广路上的上一条弧    int num[maxn];        // 距离标号计数    void AddEdge(int from, int to, int cap)    {        edges.push_back(Edge(from, to, cap, 0));        edges.push_back(Edge(to, from, 0, 0));        m = edges.size();        G[from].push_back(m-2);        G[to].push_back(m-1);    }    bool BFS()    {        memset(vis, 0, sizeof(vis));        queue<int> Q;        Q.push(t);        vis[t] = 1;        d[t] = 0;        while(!Q.empty())        {            int x = Q.front();            Q.pop();            for(int i = 0; i < G[x].size(); i++)            {                Edge& e = edges[G[x][i]^1];                if(!vis[e.from] && e.cap > e.flow)                {                    vis[e.from] = 1;                    d[e.from] = d[x] + 1;                    Q.push(e.from);                }            }        }        return vis[s];    }    void init(int n)    {        this->n = n;        for(int i = 0; i < n; i++) G[i].clear();        edges.clear();    }    int Augment()    {        int x = t, a = INF;        while(x != s)        {            Edge& e = edges[p[x]];            a = min(a, e.cap-e.flow);            x = edges[p[x]].from;        }        x = t;        while(x != s)        {            edges[p[x]].flow += a;            edges[p[x]^1].flow -= a;            x = edges[p[x]].from;        }        return a;    }    int Maxflow(int s, int t, int need)    {        this->s = s;        this->t = t;        int flow = 0;        BFS();        memset(num, 0, sizeof(num));        for(int i = 0; i < n; i++) num[d[i]]++;        int x = s;        memset(cur, 0, sizeof(cur));        while(d[s] < n)        {            if(x == t)            {                flow += Augment();                if(flow >= need) return flow;                x = s;            }            int ok = 0;            for(int i = cur[x]; i < G[x].size(); i++)            {                Edge& e = edges[G[x][i]];                if(e.cap > e.flow && d[x] == d[e.to] + 1)   // Advance                {                    ok = 1;                    p[e.to] = G[x][i];                    cur[x] = i; // 注意                    x = e.to;                    break;                }            }            if(!ok)   // Retreat            {                int m = n-1; // 初值注意                for(int i = 0; i < G[x].size(); i++)                {                    Edge& e = edges[G[x][i]];                    if(e.cap > e.flow) m = min(m, d[e.to]);                }                if(--num[d[x]] == 0) break;                num[d[x] = m+1]++;                cur[x] = 0; // 注意                if(x != s) x = edges[p[x]].from;            }        }        return flow;    }} sol;int m, s, x, y, d, S, T;int check(){    int ret = 0;    for(int i = 1; i <= m; i ++)    {        if(abs(in[i] - out[i]) & 1) return -1;        int tmp = (in[i] - out[i]) / 2;        if(in[i] > out[i])        {            ret += tmp;            sol.AddEdge(S, i, tmp);        }        else        {            sol.AddEdge(i, T, -tmp);        }    }    for(int i = 1; i <= m; i ++)        for(int j = 1; j <= m; j ++)            if(mp[i][j]) sol.AddEdge(i, j, mp[i][j]);    return ret;}int main(){    int n;    scanf("%d", &n);    while(n --)    {        scanf("%d%d", &m, &s);        CLR(mp, 0);CLR(in, 0); CLR(out, 0);        for(int i = 0; i < s; i ++)        {            scanf("%d%d%d", &x, &y, &d);            in[y] ++;            out[x] ++;            if(!d) mp[y][x] ++;        }        sol.init(m + 2);        S = 0, T = m + 1;        int flow = check();        if(~flow)        {            if(sol.Maxflow(S, T, INF) == flow)                puts("possible");            else puts("impossible");        }        else puts("impossible");    }}


0 0