zoukankan      html  css  js  c++  java
  • 混合图欧拉回路

    http://acm.pku.edu.cn/JudgeOnline/problem?id=1273

    给一组边 有的是有向边有的是无向边 问是否存在欧拉回路

    我们知道如果每个点入度等于出度 就存在欧拉回路

    这里有无向边 可以任意指定方向, 有向边已经没法改了 只统计度数 不加边

    那我们不妨指定方向为u->v 然后尝试更改这些边的方向来使每个点入度等于出度

    使边u->v反向 那么u的出度-1 入度+1, v出度+1 入度-1

    可以开个det数组 存每个点的出度减入度 通过改变边u->v的方向 使det[u]-=2, det[v]+=2

    det为0时这个点出度等于入度 也就是说如果det为奇数一定没有欧拉回路

    det[i]>0 加边st->i(权值为det[i]/2) det[i]<0 加边i->ed(权值为-det[i]/2)  (权值表示需要逆的边数)

    跑个网络流 如果每个st出发的边都为满流 就有欧拉回路

    因为考虑一个st...i...j...k...ed的增广路

    路径上的边全部反向 det[i]-=2 det[k]+=2 det[j]不变

    如果能给每个st出发的边都加上满流 那么就能所有点det为0

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int maxn = 207, maxm = 1007, inf = 0x3f3f3f3f;
    struct Edge{
        int u, v, w, f, nxt;
        Edge(){}
        Edge(int u, int v, int w, int f, int nxt):u(u), v(v), w(w), f(f), nxt(nxt){}
    }edge[maxm*2];
    int head[maxn], cur[maxn], gap[maxn], dep[maxn], pre[maxn], n, m, tot, st, ed;
    int in[maxn], out[maxn], change[maxn];
    void addedge(int u, int v, int w){
        edge[tot] = Edge(u, v, w, 0, head[u]);
        head[u] = tot++;
        edge[tot] = Edge(v, u, 0, 0, head[v]);
        head[v] = tot++;
    }
    void init(){
        tot = 0;
        memset(head, -1, sizeof head);
        memset(in, 0, sizeof in);
        memset(out, 0, sizeof out);
        memset(change, 0, sizeof change);
    }
    int sap(){
        memset(dep, 0, sizeof dep);
        memset(gap, 0, sizeof gap);
        memcpy(cur, head, sizeof head);
        int u = st;
        gap[0] = n;
        pre[u] = -1;
        int ans = 0;
        while(dep[st] < n){
            if(u == ed){
                int MIN = inf;
                for(int i = pre[ed]; ~i; i = pre[edge[i].u]){
                    if(MIN > edge[i].w-edge[i].f)
                        MIN = edge[i].w-edge[i].f;
                }
                for(int i = pre[ed]; ~i; i = pre[edge[i].u]){
                    edge[i].f += MIN;
                    edge[i^1].f -= MIN;
                }
                ans += MIN;
                u = st;
                continue;
            }
            int v= 0;
            bool flag = false;
            for(int i = cur[u]; ~i; i = edge[i].nxt){
                v = edge[i].v;
                if(edge[i].w-edge[i].f && dep[u] == dep[v]+1){
                    pre[v] = i;
                    cur[u] = i;
                    flag = true;
                    break;
                }
            }
            if(flag){
                u = v;
                continue;
            }
            int MIN = n;
            for(int i = head[u]; ~i; i = edge[i].nxt){
                int v = edge[i].v;
                if(MIN > dep[v] && edge[i].w-edge[i].f){
                    MIN = dep[v];
                    cur[u] = i;
                }
            }
            gap[dep[u]]--;
            if(!gap[dep[u]])
                return ans;
            dep[u] = MIN+1;
            gap[dep[u]]++;
            if(u != st)
                u = edge[pre[u]].u;
        }
        return ans;
    }
    bool judge(){
        int sum = 0;
        for(int i = 1; i <= n; i++){
            out[i] = out[i]-in[i];
            if(!change[i] && out[i])
                return false;
            if(out[i]&1)
                return false;
            out[i] /= 2;
            if(out[i]<0){
                out[i] = -1*out[i];
                addedge(i, ed, out[i]);
            }
            else if(out[i] == 0)
                continue;
            else{
                sum += out[i];
                addedge(st, i, out[i]);
            }
        }
        n+=2; // mmmmmmp
        int ans = sap();
        //printf("%d %d
    ", sum, ans);
        return sum == ans;
    }
    int main(){
        int t;
        scanf("%d", &t);
        while(t--){
            init();
            scanf("%d%d", &n, &m);
            st = 0, ed = n+1;
            while(m--){
                int u, v, jud;
                scanf("%d%d%d", &u, &v, &jud);
                out[u]++;
                in[v]++;
                if(!jud){
                    addedge(u, v, 1);
                    change[u] = change[v] = 1;
                }
            }
            if(judge())
                printf("possible
    ");
            else
                puts("impossible");
        }
        return 0;
    }
    搞图论是没有用的,转行做数学题了hh
  • 相关阅读:
    java事件处理(贪吃蛇)
    九九乘法表
    使用文件包含指令include
    jsp页面的基本构成
    软件测试博客

    成功职业女性处世的10大秘诀
    再见啦,冬冬妹
    网摘——杜晓眼眼中的尹珊珊:什么都要,什么都要得到
    网摘——事关“工程师思维”
  • 原文地址:https://www.cnblogs.com/DearDongchen/p/7613226.html
Copyright © 2011-2022 走看看