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

比赛时没敢写....

题意

一共同拥有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. 重温委托(delegate)和事件(event)

    1.delegate是什么 某种意义上来讲,你可以把delegate理解成C语言中的函数指针,它允许你传递一个类A的方法m给另一个类B的对象,使得类B的对象能够调用这个方法m,说白了就是可以把方法当作 ...

  2. spring配置日志

    原文:http://blog.csdn.net/xiejx618/article/details/41698913 参考:http://spring.io/blog/2009/12/04/loggin ...

  3. 手机游戏产品经理(一)logo的印象非常重要,以促进

    从事的工作有一段时间的产品,在产品上共享所以现在的一些经验和知识,并记录.首先,我现在做国外casino手游,如此专注casino展开游戏的主题. 首先说一款游戏的logo非常重要,假设设计的好.它能 ...

  4. JDBC数据库连接

    JDBC是什么? Java Data Base Connectivity JDBC是: 以统一方式訪问数据库的API,能够訪问不论什么类型表列数据.特别是存储在关系数据中的数据.JDBC代表Java数 ...

  5. C#的百度地图开发(一)发起HTTP请求

    原文:C#的百度地图开发(一)发起HTTP请求 百度地图的开发文档中给出了很多的事例,而当用到具体的语言来开发时,又会有些差异.我是使用C#来开发的.在获取相应的数据时,需要通过URL传值,然后获取相 ...

  6. ActiveMQ源码架构解析第一节(转)

    工作四年已久,也快到了而立之年,本人也酷爱技术,总是想找一些途径来提升自己,想着温故而知新所以就写起了博客,然而写博客这个想法也是酝酿了很久,近期也看到了有很多人在问关于ActiveMQ的相关问题,有 ...

  7. 6 款好用的 PC+Android 同步 GTD 软件

    6 款好用的 PC+Android 同步 GTD 软件 最近老鼠工作积极性比较高(其实只要是买平板电脑的欲望在鼓舞着干劲),所以每天很多任务安排,为了不混乱,免不了要用 GTD(Go to do)软件 ...

  8. oracle ebs 12.20 安装成功其过程失败日记及总结(1)

    由于公司业务须要,须要安装oracle ebs进行 form 开发,所以就開始了痛苦oracle ebs安装之过程.刚開始是在vm中win2003 server 中安装ebs,,不知是我自已的水平太差 ...

  9. C#属性总结

    1.私有字段和公有字段的比较 类中的私有字段只能在类的内部访问,而对类的公有字段的访问却不受限制. 在以前,为了封装,程序中会尽量少使用公有字段,因为使用公有字段的话,会让程序失去控制权.所以程序中会 ...

  10. spring问题排查-调低日志等级

    问题描写叙述 1. 页面经过一次改动后,提交后页面出现400错误,可是后台并没有输出不论什么错误信息. 2. debug监听应页面对应的提交链接也没有不论什么反应(没有进入后台的controller方 ...