zoukankan      html  css  js  c++  java
  • Random Maze HDU

    Random Maze

    Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1669    Accepted Submission(s): 682


    Problem Description
    In the game “A Chinese Ghost Story”, there are many random mazes which have some characteristic:
    1.There is only one entrance and one exit.
    2.All the road in the maze are unidirectional.
    3.For the entrance, its out-degree = its in-degree + 1.
    4.For the exit, its in-degree = its out-degree + 1.
    5.For other node except entrance and exit, its out-degree = its in-degree.

    There is an directed graph, your task is removing some edge so that it becomes a random maze. For every edge in the graph, there are two values a and b, if you remove the edge, you should cost b, otherwise cost a.
    Now, give you the information of the graph, your task if tell me the minimum cost should pay to make it becomes a random maze. 

     
    Input
    The first line of the input file is a single integer T.
    The rest of the test file contains T blocks. 
    For each test case, there is a line with four integers, n, m, s and t, means that there are n nodes and m edges, s is the entrance's index, and t is the exit's index. Then m lines follow, each line consists of four integers, u, v, a and b, means that there is an edge from u to v. 
    2<=n<=100, 1<=m<=2000, 1<=s, t<=n, s != t. 1<=u, v<=n. 1<=a, b<=100000
     
    Output
    For each case, if it is impossible to work out the random maze, just output the word “impossible”, otherwise output the minimum cost.(as shown in the sample output)
     
    Sample Input
    2 2 1 1 2 2 1 2 3 5 6 1 4 1 2 3 1 2 5 4 5 5 3 2 3 3 2 6 7 2 4 7 6 3 4 10 5
     
    Sample Output
    Case 1: impossible Case 2: 27
     
    Source
     
    Recommend
    lcy

    解析:

      每条边由两种选择,删除还是不删除,这两者所用的权值都是正数,如果一正一负是不是就是最大权闭合子图

    其实这题就和欧拉路的混合图建边一样 先定向建边 然后反悔

    但这个不是 ,所以我们可以对一条边进行假设,如果边 u - > v 的 a < b 那么我们在原图中就保留这条边 sum += a,网络图中 建一条v - > u的反向边 权值为b - a  in[v]++, out[u]++ (这里统计的是原图中的度数) 如果求费用流时走了这条边就意味着 原图中不走这条边  也就是删除这条边,同理 b < a 但这一步不统计度数 因为这一步的边在原图中已经删除了

      然后in[s_]++, out[t_]++ 使得每个节点入度 = 出度

    但实际却不是这样,通过这样构建图之后,原图中并不是所有的点的入度等于出度, 所以要通过网络图进行调整,

    遍历每个点如果in[i] < out[i]  则从i 到 t 添加一条权值为out[i] - in[i]的边,注意这里in[i] out[i]是统计的原图中的度数,|out[i] - in[i]| 表示原图中出度和入度的差额 这里的权值为|out[i] - in[i]|, 而混合欧拉图中的权值为|out[i] - in[i]| / 2,知道为什么嘛。。。因为这里是删除边 而 混合欧拉图里是把边反向   嗯 是的 我和个傻子一样

    #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 rb(a) scanf("%lf", &a)
    #define rf(a) scanf("%f", &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 = 2222222, INF = 0x3f3f3f3f, LL_INF = 0x7fffffffffffffff;
    int n, m, k, q, s, t;
    int head[222], d[222], vis[222], p[222], f[222], nex[maxn];
    int in[222], out[222];
    int flow, value, cnt;
    struct node
    {
        int u, v, w, c;
    }Node[maxn];
    
    void add_(int u, int v, int w, int c)
    {
        Node[cnt].u = u;
        Node[cnt].v = v;
        Node[cnt].w = w;
        Node[cnt].c = c;
        nex[cnt] = head[u];
        head[u] = cnt++;
    }
    
    void add(int u, int v, int w, int c)
    {
        add_(u, v, w, c);
        add_(v, u, -w, 0);
    }
    
    int spfa()
    {
        deque<int> Q;
        mem(vis, 0);
        mem(p, -1);
        mem(d, INF);
        d[s] = 0;
        Q.push_front(s);
        vis[s] = 1;
        p[s] = 0, f[s] = INF;
        while(!Q.empty())
        {
            int u = Q.front(); Q.pop_front();
            vis[u] = 0;
            for(int i = head[u]; i != -1; i = nex[i])
            {
                node e = Node[i];
                    if(d[e.v] > d[u] + Node[i].w && Node[i].c > 0)
                    {
                        d[e.v] = d[u] + Node[i].w;
                        p[e.v] = i;
                        f[e.v] = min(f[u], Node[i].c);
                        if(!vis[e.v])
                        {
                            if(Q.empty()) Q.push_front(e.v);
                            else
                            {
                                if(d[e.v] < d[Q.front()]) Q.push_front(e.v);
                                else Q.push_back(e.v);
                            }
                            vis[e.v] = 1;
                        }
                    }
            }
        }
        if(p[t] == -1) return 0;
        flow += f[t]; value += f[t] * d[t];
        for(int i = t; i != s; i = Node[p[i]].u)
        {
            Node[p[i]].c -= f[t];
            Node[p[i] ^ 1].c += f[t];
        }
        return 1;
    }
    
    void max_flow()
    {
        value = flow = 0;
        while(spfa());
    }
    
    void init()
    {
        mem(head, -1);
        mem(in, 0);
        mem(out, 0);
        cnt = 0;
    }
    
    int main()
    {
        int T, kase = 0;
        rd(T);
        while(T--)
        {
            init();
            int u, v, a, b, s_, t_;
            int sum = 0, sum_flow = 0;
            rd(n), rd(m), rd(s_), rd(t_);
            s = 0, t = n + 1;
            rap(i, 1, m)
            {
                rd(u), rd(v), rd(a), rd(b);
                if(a < b)
                {
                    sum += a;
                    add(v, u, b - a, 1);
                    in[v]++, out[u]++;
                }
                else
                {
                    sum += b;
                    add(u, v, a - b, 1);
                  //  in[v]++, out[u]++;
                }
            }
          //  add(t_, s_, 0, 1);
            in[s_]++, out[t_]++;
            rap(i, 1, n)
            {
                cout << in[i] - out[i] << endl;
                if(in[i] < out[i])
                    add(i, t, 0, (out[i] - in[i]));
                else if (in[i] > out[i])
                    add(s, i, 0, (in[i] - out[i])), sum_flow += (in[i] - out[i]);
            }
            max_flow();
    //        cout << sum_flow << "   " << flow << endl;
            printf("Case %d: ", ++kase);
            if(sum_flow != flow)
            {
                ps("impossible");
            }
            else
                pd(sum + value);
    
        }
    
    
        return 0;
    }

    Random Maze

    Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1669    Accepted Submission(s): 682


    Problem Description
    In the game “A Chinese Ghost Story”, there are many random mazes which have some characteristic:
    1.There is only one entrance and one exit.
    2.All the road in the maze are unidirectional.
    3.For the entrance, its out-degree = its in-degree + 1.
    4.For the exit, its in-degree = its out-degree + 1.
    5.For other node except entrance and exit, its out-degree = its in-degree.

    There is an directed graph, your task is removing some edge so that it becomes a random maze. For every edge in the graph, there are two values a and b, if you remove the edge, you should cost b, otherwise cost a.
    Now, give you the information of the graph, your task if tell me the minimum cost should pay to make it becomes a random maze. 

     
    Input
    The first line of the input file is a single integer T.
    The rest of the test file contains T blocks. 
    For each test case, there is a line with four integers, n, m, s and t, means that there are n nodes and m edges, s is the entrance's index, and t is the exit's index. Then m lines follow, each line consists of four integers, u, v, a and b, means that there is an edge from u to v. 
    2<=n<=100, 1<=m<=2000, 1<=s, t<=n, s != t. 1<=u, v<=n. 1<=a, b<=100000
     
    Output
    For each case, if it is impossible to work out the random maze, just output the word “impossible”, otherwise output the minimum cost.(as shown in the sample output)
     
    Sample Input
    2 2 1 1 2 2 1 2 3 5 6 1 4 1 2 3 1 2 5 4 5 5 3 2 3 3 2 6 7 2 4 7 6 3 4 10 5
     
    Sample Output
    Case 1: impossible Case 2: 27
     
    Source
     
    Recommend
    lcy
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    vpp编写plugin
    vrf 命令
    vxlan + 多个vrf
    dpdk helloworld
    Go函数高级
    Go_defer
    Go递归函数
    Go作用域
    Go函数
    Go字符串
  • 原文地址:https://www.cnblogs.com/WTSRUVF/p/9947023.html
Copyright © 2011-2022 走看看