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

比赛时没敢写....

题意

一共同拥有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;
}

【最小割】HDU 4971 A simple brute force problem.的更多相关文章

  1. HDU 4971 A simple brute force problem.

    A simple brute force problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged o ...

  2. hdu - 4971 - A simple brute force problem.(最大权闭合图)

    题意:n(n <= 20)个项目,m(m <= 50)个技术问题,做完一个项目能够有收益profit (<= 1000),做完一个项目必须解决对应的技术问题,解决一个技术问题须要付出 ...

  3. HDU 4971 - A simple brute force problem【最大权闭合图】

    有n(20)个工程,完成每个工程获得收益是p[i],m(50)个需要解决的难题,解决每个难题花费是c[i] 要完成第i个工程,需要先解决ki个问题,具体哪些问题,输入会给出 每个难题之间可能有依赖关系 ...

  4. HDU4971 A simple brute force problem.(强连通分量缩点 + 最大权闭合子图)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4971 Description There's a company with several ...

  5. A simple brute force problem.

    hdu4971:http://acm.hdu.edu.cn/showproblem.php?pid=4971 题意:给你n个项目,每完成一个项目会有一定的收益,但是为了完成某个项目,要先学会一些技能, ...

  6. hdu 4972 A simple dynamic programming problem(高效)

    pid=4972" target="_blank" style="">题目链接:hdu 4972 A simple dynamic progra ...

  7. 图论--网络流--最小割 HDU 2485 Destroying the bus stations(最短路+限流建图)

    Problem Description Gabiluso is one of the greatest spies in his country. Now he's trying to complet ...

  8. HDU 4975 A simple Gaussian elimination problem.

    A simple Gaussian elimination problem. Time Limit: 1000ms Memory Limit: 65536KB This problem will be ...

  9. hdu 4975 A simple Gaussian elimination problem.(网络流,推断矩阵是否存在)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4975 Problem Description Dragon is studying math. One ...

随机推荐

  1. 深入理解Tomcat系列之二:源码调试环境搭建(转)

    前言 最近对Tomcat的源码比较感兴趣,于是折腾了一番.要调试源码首先需要搭建环境,由于参考了几篇帖子发现都不怎么靠谱,最后还是折腾出来了,然而却花了足足一天的时间去搭建这个环境.发现都不是帖子的问 ...

  2. [置顶] Firefox OS 学习——manifest.webapp结构分析

    在Firefox OS 学习——Gaia 编译分析  这篇文章多次提到manifest.webapp文件,对于做过android app 开发的人来说,都很熟悉Android.mk 和Manifest ...

  3. PPPOE 模拟环境搭建

    这段时间.包含我自己測试OTT盒子 PPPOE的时候比較痛苦.要不就是在别人的位置上測试.要不就是借用PPPOE的设备,认为还是自己搭建一个PPPOE真实拨号上网的环境多好! 可是坑爹的win7找不到 ...

  4. HDU 4916 树分治

    Mart Master II Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  5. 每天一个JavaScript实例-递归实现反转数组字符串

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. 《Java并发编程实战》第七章 取消与关闭 读书笔记

        Java没有提供不论什么机制来安全地(抢占式方法)终止线程,尽管Thread.stop和suspend等方法提供了这种机制,可是因为存在着一些严重的缺陷,因此应该避免使用. 但它提供了中断In ...

  7. 阅读zepto.js的core中的Core methods

    学习zepto.js,參考资料:http://www.zeptojs.cn/ 跟jQuery一样.其选择符号也是$; 首先接触的是 $.()  选择 $(selector, [context]) ⇒ ...

  8. 关于SSIS批量抽取Excel文件报0x80004005错误的解决办法

    原文:关于SSIS批量抽取Excel文件报0x80004005错误的解决办法 标题: Microsoft Visual Studio ------------------------------ Pa ...

  9. Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket

    Unable to start MySQL service. Another MySQL daemon is already running with the same UNIX socket 特征 ...

  10. 为应用程序池“XX”提供服务的进程在与 Windows Process Activation Service 通信时出现严重错误

    场景 WCF应用程序部署在IIS7中,使用net.tcp协议对外给几百台客户端提供服务,应用程序池不断崩溃重启. 分析过程 在事件查看器中看到的错误信息类似于 为应用程序池“XX”提供服务的进程在与 ...