码迷,mamicode.com
首页 > 其他好文 > 详细

Random Maze HDU - 4067(预定义状态建边(贪心建边))

时间:2018-11-12 17:39:12      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:and   min   efi   cas   flow   make   contains   input   定向   

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\n", a)
#define plld(a) printf("%lld\n", a)
#define pc(a) printf("%c\n", a)
#define ps(a) printf("%s\n", 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

 

Random Maze HDU - 4067(预定义状态建边(贪心建边))

标签:and   min   efi   cas   flow   make   contains   input   定向   

原文地址:https://www.cnblogs.com/WTSRUVF/p/9947023.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!