说是最大权闭合图....

比赛时没敢写....

题意

一共有n个任务,m个技术

完成一个任务可盈利一些钱,学习一个技术要花费钱

完成某个任务前需要先学习某几个技术

但是可能在学习一个任务前需要学习另几个任务

求最多能赚多少钱咯

先将缩点将需要一起学掉的技术缩成一个点

建s--任务 权值为该任务盈利多少钱

建技术(缩点后)-t 权值为学习这技术的花费(总)

任务-技术 (完成该任务所需的每个技术都需要建边)权值为INF

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include<ctype.h>
#include<math.h>
#include<string>
#include<iostream>
#include<algorithm>
using namespace std;
#include<queue>
#include<stack>
#include<vector>
#include<deque>
#include<set>
#include<map>
//N为最大点数
#define M 150
//M为最大边数
const int MAXN = 2999;//点数的最大值
const int MAXM = 2222;//边数的最大值
const int INF = 0x3f3f3f3f;
struct Edge{int from, to, nex;bool sign;//是否为桥
}edge[M<<1];
int head[MAXN], edgenum;
void add(int u, int v){//边的起点和终点Edge E={u, v, head[u], false};edge[edgenum] = E;head[u] = edgenum++;
}int DFN[333], Low[333], Stack[333], top, Time; //Low[u]是点集{u点及以u点为根的子树} 中(所有反向弧)能指向的(离根最近的祖先v) 的DFN[v]值(即v点时间戳)
int taj;//连通分支标号,从1开始
int Belong[333];//Belong[i] 表示i点属于的连通分支
bool Instack[333];
vector<int> bcc[333]; //标号从1开始void tarjan(int u ,int fa)
{DFN[u] = Low[u] = ++ Time ;Stack[top ++ ] = u ;Instack[u] = 1 ;for (int i = head[u] ; ~i ; i = edge[i].nex ){int v = edge[i].to;if(DFN[v] == -1){tarjan(v , u);Low[u] = min(Low[u] ,Low[v]) ;if(DFN[u] < Low[v]){edge[i].sign = 1;//为割桥}}else if(Instack[v]){Low[u] = min(Low[u] ,DFN[v]) ;}}if(Low[u] == DFN[u]){int now;taj ++ ;bcc[taj].clear();do{now = Stack[-- top] ;Instack[now] = 0 ;Belong [now] = taj ;bcc[taj].push_back(now);}while(now != u) ;}
}void tarjan_init(int all){memset(DFN, -1, sizeof(DFN));memset(Instack, 0, sizeof(Instack));top = Time = taj = 0;for(int i=1;i<=all;i++)if(DFN[i]==-1 )tarjan(i, i); //注意开始点标!!!
}
vector<int>G[333];
int du[333];
void suodian(){memset(du, 0, sizeof(du));for(int i = 1; i <= taj; i++)G[i].clear();for(int i = 0; i < edgenum; i++){int u = Belong[edge[i].from], v = Belong[edge[i].to];if(u!=v){G[u].push_back(v), du[v]++;}}
}
struct Edge1
{int to,next,cap,flow;
}edge1[MAXM];//注意是MAXM
int tol;
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
//加边,单向图三个参数,双向图四个参数
void addedge (int u,int v,int w,int rw=0)
{edge1[tol].to = v;edge1[tol].cap = w;edge1[tol].next = head[u];edge1[tol].flow = 0;head[u] = tol++;edge1[tol].to = u;edge1[tol].cap = rw;edge1[tol]. next = head[v];edge1[tol].flow = 0;head[v]=tol++;
}
//输入参数:起点、终点、点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end, int N)
{memset(gap,0,sizeof(gap));memset(dep,0,sizeof(dep));memcpy(cur,head,sizeof(head));int u = start;pre[u] = -1;gap[0] = N;int ans = 0;int i;while(dep[start] < N){if(u == end){int Min = INF;for( i = pre[u];i != -1; i = pre[edge1[i^1]. to]){if(Min > edge1[i].cap - edge1[i]. flow)Min = edge1[i].cap - edge1[i].flow;}for( i = pre[u];i != -1; i = pre[edge1[i^1]. to]){edge1[i].flow += Min;edge1[i^1].flow -= Min;}u = start;ans += Min;continue;}bool flag =  false;int v;for( i = cur[u]; i != -1;i = edge1[i].next){v = edge1[i]. to;if(edge1[i].cap - edge1[i].flow && dep[v]+1 == dep[u]){flag =  true;cur[u] = pre[v] = i;break;}}if(flag){u = v;continue;}int Min = N;for( i = head[u]; i !=  -1;i = edge1[i]. next){if(edge1[i].cap - edge1[i].flow && dep[edge1[i].to] < Min){Min = dep[edge1[i].to];cur[u] = i;}}gap[dep[u]]--;if(!gap[dep[u]]) return ans;dep[u] = Min+1;gap[dep[u]]++;if(u != start) u = edge1[pre[u]^1].to;}return ans;
}
int a[MAXN],b[MAXN],cost[MAXN];
vector<int>q[222];
void init(){memset(head, -1, sizeof(head)); edgenum=0;tol=0;}
int main()
{int t,cas=1;int n, m;//n m 为点数和边数//  freopen("in.txt","r",stdin);scanf("%d",&t);while(t--){init();int sum=0;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",&a[i]);sum+=a[i];}for(int i=1;i<=m;i++){cost[i]=0;scanf("%d",&b[i]);}for(int i=1;i<=n;i++){int k,c;q[i].clear();scanf("%d",&k);for(int j=0;j<k;j++){scanf("%d",&c);q[i].push_back(c);}}for(int i=1;i<=m;i++)for(int j=1;j<=m;j++){int a;scanf("%d",&a);if(a)add(i,j);}tarjan_init(m);suodian();for(int i=1;i<=m;i++){int v=Belong[i];cost[v]+=b[i];}init();int s=0,end=taj+n+1;for(int i=1;i<=n;i++){addedge(s,taj+i,a[i],0);}for(int i=1;i<=n;i++){for(int j=0;j<q[i].size();j++){addedge(taj+i,Belong[q[i][j]+1],INF,0);}}for(int i=1;i<=taj;i++){addedge(i,end,cost[i],0);for(int j=0;j<G[i].size();j++){addedge(i,G[i][j],INF,0);}}printf("Case #%d: ",cas++);printf("%d\n",sum-sap(s,end,taj+n+2));}return 0;
}

转载于:https://www.cnblogs.com/kewowlo/p/4002483.html

【最小割】HDU 4971 A simple brute force problem.相关推荐

  1. hdu 3046(最小割)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3046 思路:最小割的入门题,设源点为0,汇点为n*m+1,源点与点为2的连一天容量为inf的边,汇点与 ...

  2. 【HDU】4859 海岸线 黑白染色+最小割

    传送门:[HDU]4859 题目分析: 最小割的思想真是博大精深! 本题的模型是最小割. 我们需要最大化海岸线的长度,如果相邻两点属性不同才会存在海岸线(海和陆地),所以我们可以将题目转化成最小化不是 ...

  3. HDU 4859 海岸线 最小割

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4859 题解: 这题考察的是最小割. 我们可以这样想:海岸线的长短变化都是E引起的,我们通过把'E'变 ...

  4. 【最小割】HDU 3987 Harry Potter and the Forbidden Forest

    得到的最小割得到sum sum/E 为 最小割 sum%E 为最小割的边数 #include <stdio.h> #include <string.h> #include &l ...

  5. HDU 3046 Pleasant sheep and big big wolf 最小割

    题意: 给定n*m个点的矩阵 0为空点.1为羊.2为狼 相邻点之间有一条路. 问要使得狼与羊不连通最少要去掉几条边 最小割 #include<stdio.h> #include<st ...

  6. hdu 3987(最小割的边数)

    题意:给出一张有n个点的图,有的边又向,有的边无向,现在要你破坏一些路,使得从点0无法到达点n-1.破坏每条路都有一个代价.求在代价最小的前提下,最少需要破坏多少条道路.(就是说求在最小割的前提下,最 ...

  7. hdu 3046(最小割最大流)

    题意:在一个单位方格边长为1的矩阵中藏着灰太狼和它的同伴,等待着喜羊羊和它的同伴,为了不让喜羊羊和同伴被抓住,我们可以在矩形草坪中设置单位长度为1的栅栏,求最短的栅栏长度. 解题思路:这道题是要把狼和 ...

  8. hdu 3879(最小割模型求解最大权闭合图)

    题意: 公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要 ...

  9. hdu 4289(最小割最大流定理)

    题意:有N个城市,现在城市S出现了一伙歹徒,他们想运送一些炸弹到D城市,不过警方已经得到了线报知道他们的事情,不过警察不知道他们所在的具体位置,所以只能采取封锁城市的办法来阻断暴徒,不过封锁城市是需要 ...

  10. hdu 6852Path6(最短路+最小割)

    传送门 •题意 有n个城市,标号1-n 现花费最小的代价堵路 使得从1号城市到n号城市的路径边长 (注意只是变长不是最长) 堵一条路的代价是这条路的权值 •思路 在堵路以前,从1到n的最小路径当然是最 ...

最新文章

  1. tomcat 部署:直接访问域名访问项目
  2. 用户画像|产品经理应该如何定位用户
  3. 用Java编写模仿的太阳系(九星行旋转)--原创
  4. 最小代价(区间dp)(ybtoj)
  5. jquery-file-upload限制文件上传大小和文件个数
  6. 芯片14纳米与7纳米相比,是不是芯片大一点,性能差不太多呢?
  7. 二维树状数组(水题) POJ1195
  8. JSONObject以及json(转)
  9. js日期函数表达天,时,分,秒
  10. 金三银四面试季—20道精选JVM重点面试问题!
  11. 如果没有证据,判断一个事件的主谋的方法
  12. IDEA使用教程----超级全
  13. 微信pc无法卡开word文件,点击文件提示“目录名无效“
  14. pacman 查询_pacman (简体中文)
  15. 大一计算机时间差怎么求,总结:如何使用Excel计算时差和日期差,只需阅读本文!...
  16. 信噪比(SNR)计算公式的推导
  17. 【每日早报】2019/08/12
  18. C#结合天敏VC4000采集卡视频监控
  19. 国民技术MCU产品类别介绍——速记分类
  20. charger在充电达到75%停止充电

热门文章

  1. Exchange Server 2007迁移Exchange Server 2010 (15)---启用Outlook anywhere
  2. Silverlight 2.0的了解
  3. linux sed用法
  4. [Swift]LeetCode1009. 十进制整数的补码 | Complement of Base 10 Integer
  5. byte[] 数组和字符串的转换,与byte[] 数组和int类型的之间的转化
  6. sql server 纵横表的转换
  7. Js、jquery学习笔记
  8. Proteus:51仿真入门
  9. 精简ICO图标可减小EXE程序文件大小
  10. 【JavaScript基础笔记】数据类型转换、false值、内存图、垃圾回收和深浅拷贝简易概念...