HDU 3917 Road constructions (最小割---最大权闭包)经典

Road constructions

Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1475    Accepted Submission(s): 489

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

2011 Multi-University Training Contest 8 - Host
by HUST

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

解题:建图:vs=0为源点,vt = m+1 为汇点。i , j  为公司,tex[ i ]为交的税,cost[ i ]为 i 公司建设道路国家需支付的花费。

1:< vs ,  i , tex[ i ] >

2:<  i  ,  vt , cost [ i ]  >

3:<  i  ,  j  ,  INF  >  (如果 i 公司与 j  公司有关联)

ans  =  sum{ tex[i]:  1<= i <= m}  -  maxflow(即最小割)。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
#define captype int

const int MAXN = 5010;   //点的总数
const int MAXM = 400010;    //边的总数
const int INF = 1<<30;
struct EDG{
    int to,next;
    captype cap;
} edg[MAXM];
int eid,head[MAXN];
int gap[MAXN];  //每种距离(或可认为是高度)点的个数
int dis[MAXN];  //每个点到终点eNode 的最短距离
int cur[MAXN];  //cur[u] 表示从u点出发可流经 cur[u] 号边
int pre[MAXN];

void init(){
    eid=0;
    memset(head,-1,sizeof(head));
}
//有向边 三个参数,无向边4个参数
void addEdg(int u,int v,captype c,captype rc=0){
    edg[eid].to=v; edg[eid].next=head[u];
    edg[eid].cap=c;  head[u]=eid++;

    edg[eid].to=u; edg[eid].next=head[v];
    edg[eid].cap=rc;  head[v]=eid++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
    memset(gap,0,sizeof(gap));
    memset(dis,0,sizeof(dis));
    memcpy(cur,head,sizeof(head));
    pre[sNode] = -1;
    gap[0]=n;
    captype ans=0;  //最大流
    int u=sNode;
    while(dis[sNode]<n){   //判断从sNode点有没有流向下一个相邻的点
        if(u==eNode){   //找到一条可增流的路
            captype Min=INF ;
            int inser;
            for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to])    //从这条可增流的路找到最多可增的流量Min
            if(Min>=edg[i].cap){
                Min=edg[i].cap;
                inser=i;
            }
            for(int i=pre[u]; i!=-1; i=pre[edg[i^1].to]){
                edg[i].cap-=Min;
                edg[i^1].cap+=Min;  //可回流的边的流量
            }
            ans+=Min;
            u=edg[inser^1].to;
            continue;
        }
        bool flag = false;  //判断能否从u点出发可往相邻点流
        int v;
        for(int i=cur[u]; i!=-1; i=edg[i].next){
            v=edg[i].to;
            if(edg[i].cap>0 && dis[u]==dis[v]+1){
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if(flag){
            u=v;
            continue;
        }
        //如果上面没有找到一个可流的相邻点,则改变出发点u的距离(也可认为是高度)为相邻可流点的最小距离+1
        int Mind= n;
        for(int i=head[u]; i!=-1; i=edg[i].next)
        if(edg[i].cap>0 && Mind>dis[edg[i].to]){
            Mind=dis[edg[i].to];
            cur[u]=i;
        }
        gap[dis[u]]--;
        if(gap[dis[u]]==0) return ans;  //当dis[u]这种距离的点没有了,也就不可能从源点出发找到一条增广流路径
                                        //因为汇点到当前点的距离只有一种,那么从源点到汇点必然经过当前点,然而当前点又没能找到可流向的点,那么必然断流
        dis[u]=Mind+1;//如果找到一个可流的相邻点,则距离为相邻点距离+1,如果找不到,则为n+1
        gap[dis[u]]++;
        if(u!=sNode) u=edg[pre[u]^1].to;  //退一条边
    }
    return ans;
}
struct NODE{
    int to,comp;
};
vector<NODE>mp[1005];
int main()
{
    int n,m,k,u,v,company,cost[MAXN],c;
    NODE now ;
    while(scanf("%d%d",&n,&m)>0&&n+m!=0)
    {
        init();
        int vs = 0 , vt = m+1 , ans = 0;
        for(int i=1; i<=m; i++){
            scanf("%d",&v);
            addEdg( vs , i , v );
            cost[i] = 0;
            ans += v;
        }
        for(int i=1; i<=n; i++)
             mp[i].clear();

        scanf("%d",&k);
        while(k--){
            scanf("%d%d%d%d",&u,&v,&company ,&c);
            cost[company] += c;
            now.to = v ; now.comp = company ;
            mp[u].push_back(now);
        }
        for(int i=1; i<=m; i++)
            addEdg( i , vt , cost[i]);
        for(int i=1; i<=n; i++)
            for(int l=mp[i].size()-1; l>=0; l-- )
             {
                  u = mp[i][l].to;
                  int comp1 = mp[i][l].comp;
                  for(int r=mp[u].size()-1; r>=0; r--)
                  {
                      int comp2 = mp[u][r].comp;
                      if(comp1==comp2)continue;
                      addEdg( comp1 , comp2 , INF );
                  }
             }
        ans -= maxFlow_sap( vs , vt , vt+1 );
        printf("%d\n",ans );
    }
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 18:00:38

HDU 3917 Road constructions (最小割---最大权闭包)经典的相关文章

HDU 3917 Road constructions(最小割---最大权闭合)

题目地址:HDU 3917 这题简直神题意...题目本身就很难看懂不说..即使看懂了,也对这题意的逻辑感到无语...不管了..就按照那题意上说的做吧... 题意:给你n个城市,m个公司,若干条可能要建设的道路,每条有向道路需要花费,还有负责建设这条道路的公司编号,如果要建设ab道路,那么负责这条道路的公司需要建设完它负责的所有道路,而且对负责道路bx(x任意)的公司同样要求,以此类推. 每个公司还要交税,问最多能收多少税. 按照题意来的话,相当于某些公司对某些公司有依赖性.最终的利润==收的税-

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 transportatio

HDU 3996 Gold Mine(最小割---最大权闭合)

题目地址:HDU 3996 很简单的最大权闭合题,只不过有个小小的坑点..那就是需要用int64....但是为什么我交上去返回的TLE.... 建图思路:分别对每一层的金矿都编号.方便处理.然后源点连接正权点,汇点连接负权点,每个点连接它所依赖的. 用正权之和减去最大流即为答案. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include

HDU 4971 A simple brute force problem.(最小割---最大权闭合)

题目地址:HDU 4971 比赛的时候还不会最大权闭合,当时还跟队友讨论了好长时间费用流和DP..现在看来就是一最大权闭合水题... 建图思路:源点连工程,权值为利润,汇点连科技项目,权值为花费,然后对有依赖性的连有向边.用正权值和减去最小割就是答案. #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #in

HDU 3061 Battle(最小割----最大权闭合图)

题目地址:HDU 3061 多校中遇到的最小割的最大权闭合模型花了一上午时间终于看懂啦. 最大权闭合图就是将一些互相有依赖关系的点转换成图,闭合图指的是在图中的每一个点的后继点都是在图内的. 还要明白简单割的概念,就是指所有的割边都与源点或汇点相连.然后让源点与正权点相连,汇点与负权点相连,权值均为其绝对值,有依赖关系的点连一条有向边,如果a必须在b的基础上,那么就连一条a->b的有向边,权值为INF.最后用所有正权值得和减去最小割的值就是答案. 具体证明可看胡伯涛大牛的国家队集训论文<最小割

HDU 3061 Battle(最小割 之 最大权闭包)经典

Battle Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 983    Accepted Submission(s): 477 Problem Description 由于小白同学近期习武十分刻苦,很快被晋升为天策军的统帅.而他上任的第一天,就面对了一场极其困难的战斗: 据侦查兵回报,前方共有N座城池,考虑到地势原因,最终得到一个结

HDU 5889 Barricade (bfs + 最小割)

Barricade Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description The empire is under attack again. The general of empire is planning to defend his castle. The land can be seen as N towns and M roads, and each

hdu 3870(平面图最小割转最短路)

Catch the Theves Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 65768/32768 K (Java/Others)Total Submission(s): 1640    Accepted Submission(s): 514 Problem Description A group of thieves is approaching a museum in the country of zjsxzy,now t

hdu 4289 Control(最小割 + 拆点)

http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2247    Accepted Submission(s): 940 Problem Description You, the head of Department of Secu