• hdu 3917 Road constructions 最大权闭合子图


    Road constructions

    Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1470    Accepted Submission(s): 485


    Problem Description
    N cities are required to connect with each other by a new transportation system. After several rounds of bidding, we have selected M constructions companies and
    decided which section is assigned to which company, the associated cost and the direction of each road.

    Due to the insufficiency of national fiscal revenue and special taxation system (the tax paid by each company pays is a fixed amount and tax payment occurs at the
    beginning of the construction of the project)   The government wishes to complete the project in several years and collects as much tax as possible to support the public
    expense

    For the restrictions of construction and engineering techniques, if a company is required to start the construction, then itself and its associated companies have to
    complete all the tasks they commit (if company A constructs a road
    from city 1 to city 2, company B constructs a road from city 2 to city 3, company C constructs a road from city 1 to city 3, we call
    companies A and B are associated and other company pairs have no such relationship, pay attention, in this example and a are not associated, in other words,’
    associated' is a directed relationship).   
    Now the question is what the maximum income the government can obtain in the first year is?
     
    Input
    There are multiple cases (no more than 50).
      Each test case starts with a line, which contains 2 positive integers, n and m (1<=n<=1000, 1<=m<=5000).
      The next line contains m integer which means the tax of each company.
      The Third line has an integer k (1<=k<=3000)which indicates the number of the roads.
      Then k lines fellow, each contains 4 integers, the start of the roads, the end of the road, the company is responsible for this road and the cost of the road.
      The end of the input with two zero
     
    Output
    For each test case output the maximum income in a separate line, and if you can not get any income, please output 0.
     
    Sample Input
    4 2 500 10 4 1 2 1 10 2 3 1 20 4 3 1 30 1 4 2 60 4 2 500 100 5 1 2 1 10 2 3 1 20 4 3 1 30 4 3 2 10 1 4 2 60 3 1 10 3 1 2 1 100 2 3 1 100 3 1 1 100 0 0
     
    Sample Output
    440 470 0
    Hint
    for second test case, if you choose company 2 responsible ways, then you must choose the path of responsible company 1, but if you choose company 1, then you do not have to choose company 2.
     
    题意:政府要雇佣公司来修建道路。雇佣公司可以获得税收,也就是利润。
    先给出N和M表示N个城市和M个公司。然后给出每个公司可以获得利润。
    然后给出一个k,表示有k条道路。
    每条道路给出道路的开始位置,道路的结束位置,修建这条道路的公司,和政府需要给点补贴,也就是所需要的花费。
    如果有两个公司,A修建一个1->2的道路,B修建一条2->3的道路,那么称A和B是有关系的,并且这种关系是单向的,也就是说,选择了A就必须要选择B。
    并且如果选择来公司A,则A承包的所有道路都要修建。问政府可以获得多少利润。
     
    思路:
    最大权闭合子图。题目中给出点关系选择A必须要选择B就是一种必要条件。
    所以设置源点s和汇点t。
    如果选择A公司必须要选择B公司,则由A点向B点连接一条容量为正无穷点边。
    连接每个点和源点s,容量为选择这个公司所获得的利润。
    连接每个点和汇点t,容量为选择这个公司后所需要修建的所有道路的花费。
    然后求最小割。
    答案就是 所有公司利润之和-最小割。
    要注意点是如果答案<0 则输出0.
    #include <bits/stdc++.h>
    using namespace std;
    int N, M;
    #define maxn 5010
    const int inf = 0x3f3f3f3f;
    struct Edge
    {
        int from, to, cap, flow;
        Edge(int f, int t, int c, int fl)
        {
            from = f; to = t; cap = c; flow = fl;
        }
    };
    struct Road
    {
        int st, ed, oer, cost;
    }road[3010];
    vector <Edge> edges;
    vector <int> G[maxn];
    int n, m, s, t;
    int d[maxn], cur[maxn], vis[maxn];
    void AddEdge(int from, int to, int cap)
    {
        edges.push_back(Edge(from, to, cap, 0));
        edges.push_back(Edge(to, from, 0, 0));
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    bool bfs()
    {
        memset(vis, 0, sizeof(vis));
        vis[s] = 1;
        d[s] = 0;
        queue <int> q;
        q.push(s);
        while(!q.empty())
        {
            int u = q.front(); q.pop();
            for(int i = 0; i < G[u].size(); i++)
            {
                Edge &e = edges[G[u][i]];
                if(!vis[e.to] && e.cap > e.flow)
                {
                    vis[e.to] = 1;
                    d[e.to] = d[u]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int dfs(int x, int a)
    {
        if(x == t || a == 0) return a;
        int flow = 0, f;
        for(int &i = cur[x]; i < G[x].size(); i++)
        {
            Edge &e = edges[G[x][i]];
            if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
            {
                e.flow += f;
                edges[G[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(a == 0) break;
            }
        }
        return flow;
    }
    int Maxflow()
    {
        int flow = 0;
        while(bfs())
        {
            memset(cur, 0, sizeof(cur));
            flow += dfs(s, inf);
        }
        return flow;
    }
    struct Node
    {
        int pos, oer;
        Node(int p, int o)
        {
            pos = p; oer = o;
        }
    };
    vector <Node> mp[1010];
    int cost[5050];
    int main()
    {
        while(~scanf("%d%d", &N, &M) && (N+M))
        {
            edges.clear();
            for(int i = 0; i <= M+1; i++) G[i].clear();
            for(int i = 1; i <= N; i++) mp[i].clear();
    
            s = 0; t = M+1;
            int sum = 0;
            for(int i = 1; i <= M; i++)
            {
                int pro; scanf("%d", &pro);
                sum += pro;
                AddEdge(s, i, pro);
            }
            int k; scanf("%d", &k);
            memset(cost, 0, sizeof(cost));
            for(int i = 1; i <= k; i++)
            {    
                scanf("%d%d%d%d", &road[i].st, &road[i].ed, &road[i].oer, &road[i].cost);
                cost[road[i].oer] += road[i].cost;
                mp[road[i].st].push_back(Node(road[i].ed, road[i].oer));
            }
            for(int i = 1; i <= k; i++)
            {
                int noer = road[i].oer;
                int u = road[i].ed;
                for(int j = 0; j < mp[u].size(); j++)
                {
                    if(mp[u][j].oer == noer) continue;
                    AddEdge(noer, mp[u][j].oer, inf);
                }
            }
            for(int i = 1; i <= M; i++) AddEdge(i, t, cost[i]);
            
            int flow = Maxflow();
            printf("%d
    ",(sum - flow >0?sum-flow:0));
        }
        return 0;
    }
    
     
  • 相关阅读:
    酷狗大数据平台架构是如何重构的
    分层架构,前后端分离有啥坏处?
    Redis快速入门及应用
    Kafka不只是个消息系统
    提高代码质量:如何编写函数
    jquery 回车事件
    程序员的薪资是如何确定出来的?
    HTTP 错误 500.21
    制作手机浏览器显示格式的HTML页面
    操作必须使用一个可更新的查询。
  • 原文地址:https://www.cnblogs.com/titicia/p/4699805.html
Copyright © 2020-2023  润新知