USC oj 1611 XX‘s dream
来源:互联网 发布:淘宝无线访客来源 编辑:程序博客网 时间:2024/06/01 13:29
最大权闭合子图介绍:
题目链接:
http://61.187.179.71:9988/problem.php?id=1611
题目大意:XX有很多梦想,完成梦想能获得价值X,但是一个梦想需要许多种努力,每种努力可能需要消耗价值也可能得到价值,问在获得最大价值的条件下,最多可完成多少种梦想
解题思路:
最大权闭合子图模板题,梦想和源点连边,可得到价值的努力也和源点连边,会消耗价值的努力和汇点连边,跑一遍网络流得到最小割,用所有正价值的和减去最小割即可。
但是这道题还要求最多能完成多少个梦想,一般情况下可能有多种不同的割边方式能得到我们需求的最大价值,所以我们求得的不一定是最大的。
这里有一个神奇的边权放大法,将所有与源点汇点相连的边乘以一个较大的常数(至少要大于图中梦想的点数),然后再给所有的梦想与源点相连的边的权值加1,这样最后得到的最大价值再除以我们乘的常数就是我们需求的价值,最多的梦想就是源点可以到达的梦想个数,直接在残余网络中dfs一遍统计能到达的梦想点就可以了(能到达的点就是我们建的边和反向边中权值大于0的)。
伪AC代码:
//oj上数据有问题。。(别问我为什么知道,标称都跑不过去,标称跑的结果和我一样。。。)
#include <iostream>#include <cstdio>#include <vector>#include <algorithm>#include <cstdlib>#include <stack>#include <map>#include <cstring>#include <string>#include <queue>typedef long long LL;const LL INF=1e15;using namespace std;const LL MAX_V=2100;struct edge{ LL to,cap,rev; edge(LL a,LL b,LL c) { to = a; cap =b; rev = c; }};vector<edge> g[MAX_V];LL level[MAX_V];LL iter[MAX_V];bool used[MAX_V];void add_edge(LL from,LL to,LL cap ){ //cout<<from<<"--¡·"<<to<< " "<<cap<<endl; g[from].push_back(edge(to,cap,g[to].size())); g[to].push_back(edge(from,0,g[from].size()-1));}void bfs(LL s){ memset(level,-1,sizeof(level)); queue<LL> que; level[s]=0; que.push(s); while(!que.empty()) { LL v=que.front(); que.pop(); for(LL i=0; i<g[v].size(); i++) { edge &e=g[v][i]; if(e.cap>0&&level[e.to]<0) { level[e.to]=level[v]+1; que.push(e.to); } } }}LL dfs(LL v,LL t,LL f){ if(v==t) return f; for(LL &i=iter[v]; i<g[v].size(); i++) { edge &e = g[v][i]; if(e.cap >0&&level[v]<level[e.to]) { LL d = dfs(e.to,t,min(f,e.cap)); if(d>0) { e.cap-=d; g[e.to][e.rev].cap +=d; return d; } } } return 0;}LL max_flow(LL s,LL t){ LL flow =0; for(;;) { bfs(s); if(level[t]<0) return flow; memset(iter,0,sizeof(iter)); LL f; while((f=dfs(s,t,INF))>0) flow+=f; }}bool vis[MAX_V];void dfs1(LL v){ vis[v]=true; for(LL i=0; i<g[v].size(); i++) { if(g[v][i].cap>0&&(!vis[g[v][i].to])) { //cout<<v<<"-->"<<g[v][i].to<<endl; // cout<<"cap = "<<g[v][i].cap<<endl; dfs1(g[v][i].to); } }}int main(){ //cout<<INF<<endl; LL m,n; while(scanf("%I64d %I64d",&n,&m)!=EOF) { for(LL i=0; i<MAX_V; i++) g[i].clear(); LL total=0; for(LL i=1; i<=n; i++) { LL dream; scanf("%I64d",&dream); add_edge(0,i,dream*10000+1); total+=dream*10000+1; } for(LL i=1; i<=m; i++) { LL tr; scanf("%I64d",&tr); if(tr>=0) { add_edge(0,n+i,tr*10000); total+=tr*10000; } else add_edge(n+i,n+m+1,(-tr)*10000); } LL k; for(LL i=1; i<=n; i++) { scanf("%I64d",&k); for(LL j=1; j<=k; j++) { LL t; scanf("%I64d",&t); add_edge(i,n+t,INF); } } LL ans2=0; LL ans =(total- max_flow(0,n+m+1))/10000; //cout<<"qq"<<endl; memset(vis,0,sizeof(vis)); dfs1(0); for(LL i=1;i<=n;i++) if(vis[i]) ans2++; printf("%I64d %I64d\n",ans,ans2); } return 0;}
0 0
- USC oj 1611 XX‘s dream
- USC oj 1404: Search
- usc oj 1615 The contest
- yesterday`s dream
- [pku2411]Mondriaan's Dream
- POJ2411 Mondriaan's Dream
- POJ2411--Mondriaan's Dream
- POJ2411 Mondriaan's Dream
- poj2411 Mondriaan's Dream
- poj2411Mondriaan's Dream
- UPC2218: Thrall’s Dream
- poj2411Mondriaan's Dream题解
- OpenJudge1413 Mondriaan's Dream
- openjudge Mondriaan's Dream
- Mondriaan's Dream POJ2411
- ZOJ1100Mondriaan's Dream
- POJ_2411_Mondriaan's Dream
- Mondriaan's Dream
- 【JavaScript】之浏览器检测
- 【牛客网】二叉树的镜像
- java笔记
- 闭包的性能优势?
- 操作系统入门
- USC oj 1611 XX‘s dream
- 【数位DP】URAL 1057 Amount of Degrees
- hdu3559 Frost Chain (概率dp+记忆化搜索)
- 383. Ransom Note
- Java程序API数据接口
- Leetcode 22. Generate Parentheses (Medium) (cpp)
- 字符串相似度算法(编辑距离算法 Levenshtein Distance)
- Java Swing ,如何在Jframe中加入图片
- ceph部署