• HDU 3987 Harry Potter and the Forbidden Forest(边权放大法+最小割)


    Harry Potter and the Forbidden Forest

    Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 2089    Accepted Submission(s): 702

    Problem Description
    Harry Potter notices some Death Eaters try to slip into Castle. The Death Eaters hide in the most depths of Forbidden Forest. Harry need stop them as soon as.

    The Forbidden Forest is mysterious. It consists of N nodes numbered from 0 to N-1. All of Death Eaters stay in the node numbered 0. The position of Castle is node n-1. The nodes connected by some roads. Harry need block some roads by magic and he want to minimize the cost. But it’s not enough, Harry want to know how many roads are blocked at least.
     
    Input
    Input consists of several test cases.

    The first line is number of test case.

    Each test case, the first line contains two integers n, m, which means the number of nodes and edges of the graph. Each node is numbered 0 to n-1.

    Following m lines contains information about edges. Each line has four integers u, v, c, d. The first two integers mean two endpoints of the edges. The third one is cost of block the edge. The fourth one means directed (d = 0) or undirected (d = 1).

    Technical Specification

    1. 2 <= n <= 1000
    2. 0 <= m <= 100000
    3. 0 <= u, v <= n-1
    4. 0 < c <= 1000000
    5. 0 <= d <= 1
     
    Output
    For each test case:
    Output the case number and the answer of how many roads are blocked at least.
     
    Sample Input
    3
     
     
    4 5
    0 1 3 0
    0 2 1 0
    1 2 1 1
    1 3 1 1
    2 3 3 1
    6 7
    0 1 1 0
    0 2 1 0
    0 3 1 0
    1 4 1 0
    2 4 1 0
    3 5 1 0
    4 5 2 0
    3 6
    0 1 1 0
    0 1 2 0
    1 1 1 1
    1 2 1 0
    1 2 1 0
    2 1 1 1
     
    Sample Output
    Case 1: 3
    Case 2: 2
    Case 3: 2
     
    Author
    aMR @ WHU
     
    Source

    题目链接:HDU 3987

    题意就是在最小割的前提下求最少的割边数,把非0流量边放大,设$maxcap$为可能出现的最大流量值(最好为10的倍数方便计算),变成$cap = cap * maxcap + 1$,0流量的肯定是不能放大的,否则出现1个流量了。

    这样一来不会改变边的大小关系,但是流量蕴含了边数,求得的最小割一定由最少割边数构成,最后求得的最小割就是$maxflow/maxcap$,最小割边数就是$maxflow\%maxcap$。

    代码:

    #include <stdio.h>
    #include <bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 1010;
    const int M = 200010;
    struct edge
    {
        int to, nxt;
        LL cap;
        edge() {}
        edge(int _to, int _nxt, LL _cap): to(_to), nxt(_nxt), cap(_cap) {}
    };
    edge E[M << 1];
    int head[N], tot, d[N];
    
    void init()
    {
        CLR(head, -1);
        tot = 0;
    }
    inline void add(int s, int t, LL cap)
    {
        E[tot] = edge(t, head[s], cap);
        head[s] = tot++;
        E[tot] = edge(s, head[t], 0LL);
        head[t] = tot++;
    }
    int bfs(int s, int t)
    {
        CLR(d, -1);
        d[s] = 0;
        queue<int>Q;
        Q.push(s);
        while (!Q.empty())
        {
            int u = Q.front();
            Q.pop();
            for (int i = head[u]; ~i; i = E[i].nxt)
            {
                int v = E[i].to;
                if (d[v] == -1 && E[i].cap > 0LL)
                {
                    d[v] = d[u] + 1;
                    if (v == t)
                        return 1;
                    Q.push(v);
                }
            }
        }
        return ~d[t];
    }
    LL dfs(int s, int t, LL f)
    {
        if (s == t || !f)
            return f;
        LL ret = 0LL;
        for (int i = head[s]; ~i; i = E[i].nxt)
        {
            int v = E[i].to;
            if (d[v] == d[s] + 1 && E[i].cap > 0LL)
            {
                LL df = dfs(v, t, min<LL>(f, E[i].cap));
                if (df > 0LL)
                {
                    E[i].cap -= df;
                    E[i ^ 1].cap += df;
                    ret += df;
                    f -= df;
                    if (!f)
                        break ;
                }
            }
        }
        if (!ret)
            d[s] = -1;
        return ret;
    }
    LL dinic(int s, int t)
    {
        LL ret = 0LL;
        while (bfs(s, t))
            ret += dfs(s, t, 0x3f3f3f3f3f3f3f3f);
        return ret;
    }
    int main(void)
    {
        int tcase;
        scanf("%d", &tcase);
        for (int q = 1; q <= tcase; ++q)
        {
            init();
            int n, m, i;
            scanf("%d%d", &n, &m);
            for (i = 0; i < m; ++i)
            {
                int u, v, d;
                LL c;
                scanf("%d%d%I64d%d", &u, &v, &c, &d);
                if (c)
                    c = c * 1000000LL + 1LL;
                add(u, v, c);
                if (d)
                    add(v, u, c);
            }
            printf("Case %d: %I64d
    ", q, dinic(0, n - 1) % 1000000LL);
        }
        return 0;
    }
  • 相关阅读:
    洛谷P4304 [TJOI2013]攻击装置 题解
    洛谷P2172 [国家集训队]部落战争 题解
    CentOS 7.0下配置MariaDB数据库
    读《深入php面向对象、模式与实践》有感(三)
    读《深入php面向对象、模式与实践》有感(二)
    读《深入php面向对象、模式与实践》有感(一)
    Linux下配置Lamp
    自己编写php框架(一)
    php读取html文件(或php文件)的方法
    Thinkphp框架感悟(二)
  • 原文地址:https://www.cnblogs.com/Blackops/p/6385713.html
Copyright © 2020-2023  润新知