• hdu 3917 修路与公司 最大权闭合图 好题


    Road constructions

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


    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.
     
    Source
     

    题意:国家现有K条有向路可能被建设(可建可不建),每个有向路由某个公司担任修建,且国家需要支付建设此路的花费,从M个公司中选出一些公司去完成建设  这些被选出的公司所担任修建的所有相关路,如果A公司修u->2,而B公司修2->v,那么选了A公司也必须选B公(即A公司与B公司有关联)。并且这些被选出的公司需要向国家交不同的税,问国家能得到的利益最多是多少。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <map>
    #include <algorithm>
    #include <set>
    using namespace std;
    #define MM(a,b) memset(a,b,sizeof(a))
    typedef long long ll;
    typedef unsigned long long ULL;
    const int mod = 1000000007;
    const double eps = 1e-10;
    const int inf = 0x3f3f3f3f;
    const int big=50000;
    int max(int a,int b) {return a>b?a:b;};
    int min(int a,int b) {return a<b?a:b;};
    struct edge{
       int to,cap,rev;
    };
    
    vector<edge> G[5010];
    vector<int> st[1010],ed[1010];
    
    int n,m,k,level[5010],sum,iter[5010],cost[5010],tax[5010];
    
    void add_edge(int u,int v,int cap)
    {
        G[u].push_back(edge{v,cap,G[v].size()});
        G[v].push_back(edge{u,0,G[u].size()-1});
    }
    
    void bfs(int s)
    {
        queue<int> q;
        q.push(s);
        level[s]=1;
        while(q.size())
        {
            int now=q.front();q.pop();
            for(int i=0;i<G[now].size();i++)
            if(G[now][i].cap>0)
            {
                edge e=G[now][i];
                if(level[e.to]<0)
                  {
                      level[e.to]=level[now]+1;
                      q.push(e.to);
                  }
            }
        }
    }
    int dfs(int s,int t,int minn)
    {
        if(s==t)
            return minn;
        for(int &i=iter[s];i<G[s].size();i++)
        {
            edge &e=G[s][i];
            if(level[e.to]>level[s]&&e.cap>0)
            {
                int k=dfs(e.to,t,min(minn,e.cap));
                if(k>0)
                 {
                     e.cap-=k;
                     G[e.to][e.rev].cap+=k;
                     return k;
                 }
            }
        }
        return 0;
    }
    
    int max_flow(int s,int t)
    {
        int ans=0,temp;
        for(;;)
        {
            memset(level,-1,sizeof(level));
            bfs(s);
            if(level[t]<0)
                return ans;
            memset(iter,0,sizeof(iter));
            while((temp=dfs(s,t,inf))>0)
                ans+=temp;
        }
        return ans;
    }
    
    void build()
    {
        for(int i=1;i<=m;i++)
           if(cost[i]>0)
             {
                 add_edge(0,i,cost[i]);
                 sum+=cost[i];
             }
           else  if(cost[i]<0)
             add_edge(i,m+1,-cost[i]);
    
        for(int u=1;u<=n;u++)
             for(int i=0;i<st[u].size();i++)
                for(int j=0;j<ed[u].size();j++)
             {
                  int a=st[u][i],b=ed[u][j];
                  add_edge(b,a,inf);
             }
    }
    
    void init()
    {
        for(int i=0;i<=m+1;i++) G[i].clear();
        for(int i=1;i<=n;i++)
        {
            st[i].clear();
            ed[i].clear();
        }
    
        MM(cost,0);
        MM(tax,0);
    }
    
    int main()
    {
        while(~scanf("%d %d",&n,&m)&&(n||m))
        {
            init();
            sum=0;
            for(int i=1;i<=m;i++)
                    scanf("%d",&tax[i]);
    
            scanf("%d",&k);
            for(int i=1;i<=k;i++)
                 {
                     int u,v,b,c;
                     scanf("%d %d %d %d",&u,&v,&b,&c);
    
                     st[u].push_back(b);
                     ed[v].push_back(b);//st与ed的妙用,,刚开始用的麻烦的爆搜。。
                     cost[b]+=(-c);//切记转换成负数
                 }
    
            for(int i=1;i<=m;i++)
                     cost[i]+=tax[i];//构建的新图中节点值
    
            build();
    
            printf("%d
    ",sum-max_flow(0,m+1));
        }
        return 0;
    }

      分析:很好的一道题,,就是原题题意神坑,,再加上把100看成了10,,太不细心了;

    1,将原图上无法进行最大权闭合图,,想想就知道了,,转化成公司上的闭合圈最大图(选a公司那么必须选b公司),

    2.最大权闭合图中的sum-maxflow中的sum指的是需要跑最小割的新图中节点中值>0的数之和

  • 相关阅读:
    后海日记(8)
    后海日记(8)
    后海日记(7)
    后海日记(7)
    hadoop自己写的最高温度程序源码
    hadoop自己写的最高温度程序源码
    20张图为您讲述磁盘发展史
    20张图为您讲述磁盘发展史
    2017"百度之星"程序设计大赛
    汕头市赛srm1X T3
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5510665.html
Copyright © 2020-2023  润新知