最大权闭合图小结
来源:互联网 发布:汽车网站模板源码 编辑:程序博客网 时间:2024/05/22 01:42
最大权闭合图
昨天在做多校联赛的时候偶然碰上的,学习了下这个,首先推荐胡伯涛的《最小割模型在信息学竞赛中的应用》。
定义
一个有向图 的闭合图(closure)
那么,我们的做法就是当
所以我们做法就是跑一次最大流,然后最大权闭合图的权值就是总收益-最大流。
POJ2987
这是一个非常裸地最大权闭合图,当
然后直接按照原理跑一下最大流就好。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 5010#define pi acos(-1.0)#define inf 0x3f3f3f3f#define pb(x) push_back((x))typedef long long ll;typedef unsigned long long ull;struct edge{ int to,c,rev;};vector<edge> g[N];ll sum;int level[N],iter[N];int n,m;void addnode(int a,int b,int c){ g[a].push_back((edge){b,c,g[b].size()}); g[b].push_back((edge){a,0,g[a].size()-1});}void build_graph(int s,int t,int n,int m){ int tmp,u,v; for(int i=1;i<=n;i++){ scanf("%d",&tmp); if(tmp>=0){ addnode(s,i,tmp); sum+=tmp; } else addnode(i,t,-tmp); } for(int i=1;i<=m;i++){ scanf("%d%d",&u,&v); addnode(u,v,inf); }}bool bfs(int s,int t){ memset(level,-1,sizeof(iter)); queue <int> q; level[s]=0; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<g[u].size();i++){ edge e=g[u][i]; if(e.c>0&&level[e.to]==-1){ level[e.to]=level[u]+1; q.push(e.to); } } } if(level[t]==-1)return false; return true;}int dfs(int u,int t,int f){ if(u==t) return f; for(int &i=iter[u];i<g[u].size();i++){ edge &e=g[u][i]; if(e.c>0&&level[e.to]>level[u]){ int d=dfs(e.to,t,min(e.c,f)); if(d>0){ e.c-=d; g[e.to][e.rev].c+=d; return d; } } } return 0;}int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ sum=0; build_graph(0,n+1,n,m); ll ans=0; while(bfs(0,n+1)){ memset(iter,0,sizeof(iter)); int f; while((f=dfs(0,n+1,inf))>0){ ans+=f; } } bfs(0,n+1); int fire=0; for(int i=1;i<=n;i++) if(level[i]>0) fire++; printf("%d %lld\n",fire,sum-ans); for(int i=0;i<=n+1;i++) g[i].clear(); } return 0;}
HDU4971
水题。
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 110#define pi acos(-1.0)#define inf 0x3f3f3f3f#define pb(x) push_back((x))typedef long long ll;typedef unsigned long long ull;struct edge{ int to,c,rev;};vector<edge> g[N];ll sum;int level[N],iter[N];int n,m;void addnode(int a,int b,int c){ g[a].push_back((edge){b,c,g[b].size()}); g[b].push_back((edge){a,0,g[a].size()});}void build_graph(int s,int t,int n,int m){ int tmp,u,v,k; for(int i=1;i<=n;i++){ scanf("%d",&tmp); addnode(s,i,tmp); sum+=tmp; } for(int i=1;i<=m;i++){ scanf("%d",&tmp); addnode(i+n,t,tmp); } for(int i=1;i<=n;i++){ scanf("%d",&k); for(int j=1;j<=k;j++){ scanf("%d",&tmp); addnode(i,n+tmp+1,inf); } } for(int i=1;i<=m;i++){ for(int j=1;j<=m;j++){ scanf("%d",&tmp); if(tmp) addnode(n+i,n+j,inf); } }}bool bfs(int s,int t){ memset(level,-1,sizeof(iter)); queue <int> q; level[s]=0; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<g[u].size();i++){ edge e=g[u][i]; if(e.c>0&&level[e.to]==-1){ level[e.to]=level[u]+1; q.push(e.to); } } } if(level[t]==-1)return false; return true;}int dfs(int u,int t,int f){ if(u==t) return f; for(int &i=iter[u];i<g[u].size();i++){ edge &e=g[u][i]; if(e.c>0&&level[e.to]>level[u]){ int d=dfs(e.to,t,min(e.c,f)); if(d>0){ e.c-=d; g[e.to][e.rev].c+=d; return d; } } } return 0;}int main(){ int n,m,t,cnt=0; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); sum=0; build_graph(0,n+m+1,n,m); ll ans=0; while(bfs(0,n+m+1)){ memset(iter,0,sizeof(iter)); int f; while((f=dfs(0,n+1+m,inf))>0){ ans+=f; } } printf("Case #%d: %d\n",++cnt,sum-ans); for(int i=0;i<=n+m+1;i++) g[i].clear(); } return 0;}
HDU5855
首先膜拜一下朝鲜队的出题大哥,题目质量太好了。
这道题我们直接二分最短的时间,然后对于每一次时间判断一下最大权闭合图是不是大于L就好
#include <cstdio>#include <iostream>#include <cstring>#include <algorithm>#include <set>#include <queue>#include <map>#include <cmath>#include <vector>using namespace std;#define N 410#define pi acos(-1.0)#define inf 0x3f3f3f3f#define pb(x) push_back((x))typedef long long ll;typedef unsigned long long ull;struct edge{ int to,c,rev;};vector<int> shop[N];vector<edge> g[N];int level[N];int iter[N];int n,m,L,tmp1,tmp2;int pt[N],pay[N],pro[N];int sum;inline void addnode(int a,int b,int c){ g[a].push_back((edge){b,c,g[b].size()}); g[b].push_back((edge){a,0,g[a].size()-1});}inline void build_graph(int mid){//建图 for(int i=1;i<=m;i++){ bool f=true; addnode(0,i,pro[i]); for(int j=0;j<shop[i].size();j++){ addnode(i,m+shop[i][j],inf); } } for(int i=1;i<=n;i++){ if(pt[i]>mid) addnode(m+i,n+m+1,inf); else addnode(m+i,n+m+1,pay[i]); }}inline bool bfs(int s,int t){ memset(level,-1,sizeof(level)); queue <int> q; level[s]=0; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=0;i<g[u].size();i++){ edge &e=g[u][i]; if(e.c>0&&level[e.to]<0){ level[e.to]=level[u]+1; q.push(e.to); } } } if(level[t]==-1) return false; return true;}inline int dfs(int u,int t,int f){ if(u==t) return f; for(int &i=iter[u];i<g[u].size();i++){ edge &e=g[u][i]; if(e.c>0&&level[e.to]>level[u]){ int d=dfs(e.to,t,min(f,e.c)); if(d>0){ e.c-=d; g[e.to][e.rev].c+=d; return d; } } } return 0;}inline int dinic(int mid){ int ans=0; build_graph(mid); while(bfs(0,n+m+1)){ memset(iter,0,sizeof(iter)); int f; while((f=dfs(0,n+m+1,inf))>0){ ans+=f; }//循环增广 } for(int i=0;i<=n+m+1;i++) g[i].clear(); if(ans==0) return 0; //printf("ans=%d %d\n",ans,sum-ans); return sum-ans;}int main(){ int t; int maxpt; int cnt=0; scanf("%d",&t); while(t--){ scanf("%d%d%d",&n,&m,&L); int maxpt=0; sum=0; for(int i=1;i<=n;i++){ scanf("%d%d",&pay[i],&pt[i]); maxpt=max(pt[i],maxpt); } for(int i=1;i<=m;i++){ scanf("%d",&pro[i]); sum+=pro[i]; scanf("%d",&tmp1); for(int j=1;j<=tmp1;j++){ scanf("%d",&tmp2); shop[i].push_back(tmp2); } } int r=maxpt+1,l=0; tmp1=0; while(l<r){ //printf("%d %d ",l,r); int mid=(l+r)/2; if(l+1==r){ tmp1=dinic(r); //printf("tmp1= %d\n",tmp1); if(tmp1>=L){ int ptmp1=dinic(l); //printf("tmp1= %d\n",ptmp1); if(ptmp1>=L) tmp1=ptmp1; else l=r; } else l=r+1; break; } tmp1=dinic(mid); if(tmp1>=L) r=mid; else l=mid; //printf("end= %d\n",tmp1); } printf("Case #%d: ",++cnt); if(l<=maxpt){ printf("%d %d\n",l,tmp1); } else printf("impossible\n"); for(int i=1;i<=m;i++) shop[i].clear(); } return 0;}
0 0
- 最大权闭合图小结
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 最大权闭合图
- 【小结】最小费用流&最大权闭合图
- 最大权闭合图 poj2987
- 【JAVA语言程序设计基础篇】--事件驱动程序设计--键盘事件
- DataGridView DataSource INotifyPropertyChanged 避免闪烁的方法
- URL和URI区别以及相对路径和绝对路径
- 04. Yii 2.0 的MVC模式
- 《React-Native系列》19、 ListView组件之上拉刷新(iOS和Android通用)
- 最大权闭合图小结
- 雅礼联考Day1总结(《论机房网络好坏对于选手比赛成绩的消极影响》)
- 简易购物车
- 子集生成
- 每个程序员都应该收藏的算法复杂度速查表
- 剑指offer面试题:替换空格
- ios开发--storyboard里不用拖线方式来push视图
- java中的标识符、关键字、数据类型
- python初步(打印HelloWorld!)