zoukankan      html  css  js  c++  java
  • Sightseeing tour HDU

    题意:

      有n个点,m条边,其中有单向边和双向边,求是否存在欧拉回路

    解析:

      刚开始想。。。判断一下每个点的度数不就好了。。。emm。。还是年轻啊。。

      判断是解决不了问题的,因为可能会有某两个点冲突,比如说一个点出度比入度大1,但它只有一条无向边,所以这条无向边要变成入边,但这条无向边的v点也是

      出度比入度大1,也是需要一条入边,所以这样就会冲突,如果直接判断的话不会判断出来,所以就用到了网络流,

      设想一下,我们把这条无向边的容量设为1,那么如果用了这条边,容量就会为0,所以不会重复使用,且不产生冲突

    具体实现:

     不是我懒。。。是人家讲的真的很好嘛。。。

    https://blog.csdn.net/wall_f/article/details/8237520

    1、另x = |入度-出度|/2;对于不同的点有不同的x值,这个x值代表它们在邻接表中相应调整x条就能让出度等于入度。

    2、以把图中的点转换为一个二分图,每个点的x值就是它们的点权。

    3、置源点S向所有出度>入度的点连边;设置汇点T,所有入度大于出度的点连边,将各自的点权转换为边权。

    4、最后将原图中所有暂时定向的无向边加上一个1的容量,方向不变,而有向边不能改变方向,不需连边。

    可以发现,从源点S出发的一个单位流将会一个“无向边”的容量变为0,使得两端的点权各自减1,其实这就是在模拟一次对无向边方向的调整。当把图建好后,依靠最大流性质可以最大可能地无冲突调整边的方向,并最终使得每个点的点容量都达到满流。

    最后,还要对那些图中出度等于入度的点做适当分析,它们作为一个“中间点”,由于流平衡性质,不会留下任何流量值,对于那些真正需要调整的点不会带来任何影响。

    最后,如何得到答案?那就是检查从源点出发的每条边是否都满流,如果有一条边没有满流,说明有一个点没有调整到入度等于出度,于是整个图不存在欧拉回路。

    这题保证了只有一个连通块。。虽然我还判断了一下。。。

    #include <iostream>
    #include <cstdio>
    #include <sstream>
    #include <cstring>
    #include <map>
    #include <cctype>
    #include <set>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #include <bitset>
    #define rap(i, a, n) for(int i=a; i<=n; i++)
    #define rep(i, a, n) for(int i=a; i<n; i++)
    #define lap(i, a, n) for(int i=n; i>=a; i--)
    #define lep(i, a, n) for(int i=n; i>a; i--)
    #define rd(a) scanf("%d", &a)
    #define rlld(a) scanf("%lld", &a)
    #define rc(a) scanf("%c", &a)
    #define rs(a) scanf("%s", a)
    #define pd(a) printf("%d
    ", a);
    #define plld(a) printf("%lld
    ", a);
    #define pc(a) printf("%c
    ", a);
    #define ps(a) printf("%s
    ", a);
    #define MOD 2018
    #define LL long long
    #define ULL unsigned long long
    #define Pair pair<int, int>
    #define mem(a, b) memset(a, b, sizeof(a))
    #define _  ios_base::sync_with_stdio(0),cin.tie(0)
    //freopen("1.txt", "r", stdin);
    using namespace std;
    const int maxn = 10010, INF = 0x7fffffff, LL_INF = 0x7fffffffffffffff;
    int n, m, s, t, cnt;
    int f[maxn], deg[maxn], in[maxn], out[maxn], vis[maxn];
    int d[maxn], head[maxn], cur[maxn];
    set<int> ss;
    
    int find(int x)
    {
        return f[x] == x ? x : (f[x] = find(f[x]));
    }
    
    void init()
    {
        for(int i = 1; i < maxn; i++) f[i] = i;
        mem(deg, 0);
        mem(in, 0);
        mem(head, -1);
        mem(out, 0);
        cnt = 0;
    //    mem(vis, 0);
        ss.clear();
    }
    
    struct edge
    {
        int u, v, c, next;
    }Edge[maxn];
    
    void add_(int u, int v, int c)
    {
        Edge[cnt].u = u;
        Edge[cnt].v = v;
        Edge[cnt].c = c;
        Edge[cnt].next = head[u];
        head[u] = cnt++;
    }
    
    void add(int u, int v, int c)
    {
        add_(u, v, c);
        add_(v, u, 0);
    }
    
    bool bfs()
    {
        queue<int> Q;
        mem(d, 0);
        Q.push(s);
        d[s] = 1;
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop();
            for(int i = head[u]; i != -1; i = Edge[i].next)
            {
                edge e = Edge[i];
                if(!d[e.v] && e.c > 0)
                {
                    d[e.v] = d[e.u] + 1;
                    Q.push(e.v);
                    if(e.v == t) return 1;
                }
            }
        }
        return d[t] != 0;
    }
    
    int dfs(int u, int cap)
    {
        int ret = 0;
        if(u == t || cap == 0)
            return cap;
        for(int &i = cur[u]; i != -1; i = Edge[i].next)
        {
            edge e = Edge[i];
            if(d[e.v] == d[u] + 1 && e.c > 0)
            {
                int V = dfs(e.v, min(cap, e.c));
                Edge[i].c -= V;
                Edge[i^1].c += V;
                ret += V;
                cap -= V;
                if(cap == 0) break;
            }
        }
        if(cap > 0) d[u] = -1;
        return ret;
    }
    
    int Dinic(int u)
    {
        int ans = 0;
        while(bfs())
        {
            memcpy(cur, head, sizeof(head));
            ans += dfs(u, INF);
        }
        return ans;
    }
    
    int main()
    {
        int T;
        cin >> T;
        while(T--)
        {
            int u, v, w;
            cin >> n >> m;
            init();
            s = 0, t = n + 1;
            for(int i = 1; i <= m; i++)
            {
                cin >> u >> v >> w;
                in[v]++, out[u]++;
                if(u != v && w == 0) add(u, v, 1);
                int l = find(u);
                int r = find(v);
                if(l != r) f[l] = r;
            }
            int flag = 0, m_sum = 0;
            for(int i = 1; i <= n; i++)
            {
                int x = find(i);
                ss.insert(x);
                if(abs(out[i] - in[i]) & 1)
                {
                    flag = 1;
                    break;
                }
                if(out[i] > in[i]) add(s, i, (out[i] - in[i]) / 2), m_sum += (out[i] - in[i]) / 2;
                else if(in[i] > out[i]) add(i, t, (in[i] - out[i]) / 2);
    
            }
            if(flag || ss.size() > 1)
            {
                cout << "impossible" << endl;
                continue;
            }
            if(m_sum == Dinic(s))
                cout << "possible" << endl;
            else
                cout << "impossible" << endl;
    
        }
    
        return 0;
    }
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    LightOJ 1132 Summing up Powers(矩阵快速幂)
    hdu 3804 Query on a tree (树链剖分+线段树)
    LightOJ 1052 String Growth && uva 12045 Fun with Strings (矩阵快速幂)
    uva 12304 2D Geometry 110 in 1! (Geometry)
    LA 3263 That Nice Euler Circuit (2D Geometry)
    2013 SCAUCPC Summary
    poj 3321 Apple Tree (Binary Index Tree)
    uva 11796 Dog Distance (几何+模拟)
    uva 11178 Morley's Theorem (2D Geometry)
    动手动脑
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9759296.html
Copyright © 2011-2022 走看看