hdu 4971 A simple brute force problem.【最小权闭包】
来源:互联网 发布:哪款单反性价比高 知乎 编辑:程序博客网 时间:2024/05/17 09:02
A simple brute force problem.
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 729 Accepted Submission(s): 381
Problem Description
There's a company with several projects to be done. Finish a project will get you profits. However, there are some technical problems for some specific projects. To solve the problem, the manager will train his employee which may cost his budget. There may be dependencies between technical problems, for example, A requires B means you need to solve problem B before solving problem A. If A requires B and B requires A, it means that you should solve them at the same time. You can select which problems to be solved and how to solve them freely before finish your projects. Can you tell me the maximum profit?
Input
The first line of the input is a single integer T(<=100) which is the number of test cases.
Each test case contains a line with two integer n(<=20) and m(<=50) which is the number of project to select to complete and the number of technical problem.
Then a line with n integers. The i-th integer(<=1000) means the profit of complete the i-th project.
Then a line with m integers. The i-th integer(<=1000) means the cost of training to solve the i-th technical problem.
Then n lines. Each line contains some integers. The first integer k is the number of technical problems, followed by k integers implying the technical problems need to solve for the i-th project.
After that, there are m lines with each line contains m integers. If the i-th row of the j-th column is 1, it means that you need to solve the i-th problem before solve the j-th problem. Otherwise the i-th row of the j-th column is 0.
Output
For each test case, please output a line which is "Case #X: Y ", X means the number of the test case and Y means the the maximum profit.
Sample Input
4
2 3
10 10
6 6 6
2 0 1
2 1 2
0 1 0
1 0 0
0 0 0
2 3
10 10
8 10 6
1 0
1 2
0 1 0
1 0 0
0 0 0
2 3
10 10
8 10 6
1 0
1 2
0 1 0
0 0 0
0 0 0
2 3
10 10
8 10 6
1 0
1 2
0 0 0
1 0 0
0 0 0
Sample Output
Case #1: 2
Case #2: 4
Case #3: 4
Case #4: 6
Author
BJTU
Source
2014 Multi-University Training Contest 10
题目大意:
一共有N个工程,有M个问题,想要建立一个工程需要解决一些问题之后才能建立,并且问题之间有依赖关系,建立一个工程会有对应的利润,解决一个问题会有对应的花费,问怎样建立工程才能使得利润最大。思路;
1、经典的最小权闭包问题,通过求最大流来求得最小割,从而使得最大利润=总利润-最小割。
2、考虑建图:
①建立源点,连入各个工程,流设定为工程的利润。
②建立汇点,将各个问题连入汇点,流设定为各个问题的花费。
③对应一个工程连入其需要解决的问题上,流设定为INF。
那么我们首先不考虑问题的依赖关系,此时若跑最大流,得到最小割,那么其最大利润=总利润-最小割。
3、若我们现在要考虑一个依赖关系。只要考虑将工程的利润的剩余流跑入另外一个问题中即可,那么对应:
④如果有(i,j)=1.对应将问题i连入问题j,流设定为INF。
4、整个图建好之后,跑得最大流,得到最小割,那么其最大利润=总利润-最小割。
Ac代码:
#include<stdio.h>#include<string.h>#include<queue>#include<iostream>using namespace std;struct node{ int from; int to; int w; int next;}e[1000*1000*2+50];int cur[10050];int divv[10050];int head[10050];int val[10050];int cost[10050];int n,m,cont,ss,tt,sum;void add(int from,int to,int w){ e[cont].to=to; e[cont].w=w; e[cont].next=head[from]; head[from]=cont++;}void Getmap(){ memset(head,-1,sizeof(head)); cont=0; ss=n+m+1; tt=ss+1; for(int i=0;i<n;i++) { add(ss,i,val[i]); add(i,ss,0); } for(int i=0;i<m;i++) { add(i+n,tt,cost[i]); add(tt,i,0); } for(int i=0;i<n;i++) { int k; scanf("%d",&k); while(k--) { int x; scanf("%d",&x); add(i,x+n,0x3f3f3f3f); add(x+n,i,0); } } for(int i=0;i<m;i++) { for(int j=0;j<m;j++) { int x; scanf("%d",&x); if(x==1) { add(i+n,j+n,0x3f3f3f3f); add(j+n,i+n,0); } } }}int makedivv(){ queue<int >s; s.push(ss); memset(divv,0,sizeof(divv)); divv[ss]=1; while(!s.empty()) { int u=s.front(); if(u==tt)return 1; s.pop(); for(int i=head[u];i!=-1;i=e[i].next) { int v=e[i].to; int w=e[i].w; if(w&&divv[v]==0) { divv[v]=divv[u]+1; s.push(v); } } } return 0;}int Dfs(int u,int maxflow,int tt){ if(u==tt)return maxflow; int ret=0; for(int &i=cur[u];i!=-1;i=e[i].next) { int v=e[i].to; int w=e[i].w; if(w&&divv[v]==divv[u]+1) { int f=Dfs(v,min(maxflow-ret,w),tt); e[i].w-=f; e[i^1].w+=f; ret+=f; if(ret==maxflow)return ret; } } return ret;}void Slove(){ int ans=0; while(makedivv()==1) { memcpy(cur,head,sizeof(head)); ans+=Dfs(ss,0x3f3f3f3f,tt); } printf("%d\n",sum-ans);}int main(){ int t; int kase=0; scanf("%d",&t); while(t--) { sum=0; scanf("%d%d",&n,&m); for(int i=0;i<n;i++) { scanf("%d",&val[i]); sum+=val[i]; } for(int i=0;i<m;i++) { scanf("%d",&cost[i]); } Getmap(); printf("Case #%d: ",++kase); Slove(); }}
- hdu 4971 A simple brute force problem.【最小权闭包】
- 【最小割】HDU 4971 A simple brute force problem.
- HDU-4971-A simple brute force problem.
- HDU 4971 A simple brute force problem.
- HDU 4971 A simple brute force problem
- HDU 4971 A simple brute force problem.(最小割,最大权闭合图)
- HDU 4971 A simple brute force problem.(最小割---最大权闭合)
- HDU 4971 A simple brute force problem. 最小割 最大权闭合
- HDU 4971 A simple brute force problem.(最小割,最大权闭合图)
- HDU 4971 A simple brute force problem.(dp)
- HDU - 4971 A simple brute force problem. (DP)
- HDU 4971 A simple brute force problem.(最大流)
- HDU 4971 A simple brute force problem.(最大权闭合)
- hdoj 4971 A simple brute force problem. 【最大权闭合图 --> 最小割】
- HDU 4971 A simple brute force problem. 强连通缩点+最大权闭合图
- 【HDU】4971 A simple brute force problem. 强连通缩点+最大权闭合子图
- HDU 4971 A simple brute force problem. 最大权闭合图
- hdu 多校联合 4971 A simple brute force problem.(最大权闭合图)
- C++之中this指针与类的六个默认函数小结
- java 中的 split 方法要注意
- 《深入理解Java虚拟机》笔记01:走近Java
- 返回栈
- java缓存适合使用的情况
- hdu 4971 A simple brute force problem.【最小权闭包】
- 回复一位面试被拒的大四学生
- 【转载】堆、栈 的理解
- 图形学学习笔记4——平面图形裁剪
- github如何搜索资料
- php rpm安装
- 《深入理解Java虚拟机》笔记二:01-Java内存区域与内存溢出异常
- c++从SQL SERVER中读写数据、删除数据
- TCP/IP协议栈之三---------网络层