博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2039: [2009国家集训队]employ人员雇佣(最小割)
阅读量:6991 次
发布时间:2019-06-27

本文共 2676 字,大约阅读时间需要 8 分钟。

 

膜一下大佬->

不难看出这是一个最小割的模型(然而我看不出来)

我们从源点向每一个点连边,容量为他能带来的总收益(也就是他能对其他所有经理产生的贡献)

然后从每一个点向汇点连边,容量为雇佣他的费用

那么考虑一下,如果我们割了源点到他的连线,代表不选他,就损失了相当于容量的利润

如果我们割了他到汇点的连线,代表选他,那么需要支付相当于容量的代价

那么只要用所有的收益减去最小割就是答案

然而还有一个条件,如果选$i$不选$j$会有损失

那么我们从$i$到$j$连容量为$E_{i,j}*2$的边,为什么呢?因为如果我们选了$j$而不选$i$,就是割了$s->j$和$i->t$那么还存在一条$s->i->j->t$的路,那么$i->j$这条边肯定会断掉,那么就满足条件了

1 //minamoto 2 #include
3 #include
4 #include
5 #include
6 #define inf 0x7fffffff 7 #define ll long long 8 using namespace std; 9 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)10 char buf[1<<21],*p1=buf,*p2=buf;11 inline int read(){12 #define num ch-'0'13 char ch;bool flag=0;int res;14 while(!isdigit(ch=getc()))15 (ch=='-')&&(flag=true);16 for(res=num;isdigit(ch=getc());res=res*10+num);17 (flag)&&(res=-res);18 #undef num19 return res;20 }21 const int N=1005,M=5000005;22 int ver[M],Next[M],head[N],tot=1;ll edge[M];23 int dep[N],cur[N],n,m,s,t;24 queue
q;ll ans;25 inline void add(int u,int v,ll e){26 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;27 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0;28 }29 bool bfs(){30 while(!q.empty()) q.pop();31 memset(dep,-1,sizeof(dep));32 for(int i=s;i<=t;++i) cur[i]=head[i];33 q.push(s),dep[s]=0;34 while(!q.empty()){35 int u=q.front();q.pop();36 for(int i=head[u];i;i=Next[i]){37 int v=ver[i];38 if(dep[v]<0&&edge[i]){39 dep[v]=dep[u]+1,q.push(v);40 if(v==t) return true;41 }42 }43 }44 return false;45 }46 ll dfs(int u,ll limit){47 if(u==t||!limit) return limit;48 ll flow=0,f;49 for(int i=cur[u];i;i=Next[i]){50 int v=ver[i];cur[u]=i;51 if(dep[v]==dep[u]+1&&(f=dfs(v,min(limit,edge[i])))){52 flow+=f,limit-=f;53 edge[i]-=f,edge[i^1]+=f;54 if(!limit) break;55 }56 }57 if(!flow) dep[u]=-1;58 return flow;59 }60 ll dinic(){61 ll flow=0;62 while(bfs()) flow+=dfs(s,inf);63 return flow;64 }65 int main(){66 //freopen("testdata.in","r",stdin);67 n=read(),s=0,t=n+1;68 for(int i=1;i<=n;++i){69 int x=read();add(i,t,x);70 }71 for(int i=1;i<=n;++i){72 ll res=0;73 for(int j=1;j<=n;++j){74 ll x=read();75 res+=x;76 if(i!=j) add(i,j,x*2);77 }78 add(s,i,res),ans+=res;79 }80 printf("%lld\n",ans-dinic());81 return 0;82 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9570325.html

你可能感兴趣的文章
linux应用之Mongodb的安装及配置(centos)
查看>>
Python 面向对象 --- eval 函数
查看>>
PHP的错误和异常处理
查看>>
z-index兼容问题:关于ie6/7下的z-index
查看>>
腾讯2014年实习生招聘笔试面试经历
查看>>
不浮躁,获取充实感
查看>>
Pyqt 国际化多语言支持
查看>>
大多数女生为什么不适合当程序员?
查看>>
SID1190471 / 烦人的幻灯片 暴力出奇迹 !!!!!!!!!!!!!!!!!!...
查看>>
高速排序 与 随机高速排序 算法分析
查看>>
使用MyEclipse 2014构建Maven项目的两种方法
查看>>
WebGIS中以version方式实现代码更新后前端自动读取更新代码的方法
查看>>
Centos 安装Apache软件
查看>>
微信小程序中在swiper-item中遍历循环添加多个数据内容(微信小程序交流群:604788754)...
查看>>
java-mybaits-00503-延迟加载
查看>>
看淡你的权力
查看>>
Linux学习(一)
查看>>
[1-5] 把时间当做朋友(李笑来)Chapter 5 【小心所谓成功学】 摘录
查看>>
POJ 3126 Prime Path SPFA
查看>>
Shortest Path [3]
查看>>