AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3511

题目分析:

  看上去和前面的人员雇佣以及小M种田都很像。

  最小割模型来求最大值,一般都是考虑怎样构图使得满足一个组合能被表示出来,而且当满足一个组合的时候,能产生或失去所需的效益。[割掉的是不要的]

  我们将s与1相连,连为INF,这样就不会被割,n向t连边,同理。

  因为1和n会有边连接,所以我们才多建出了节点s,t。

  然后对于每个点i,s向i连wa[i],i向t连wb[i],这样就满足了第一条性质。

  对于ea,eb,ec的弄法,我们就先从s向u和向v连ea/2,从u和v向t连eb/2,然后在uv之间连一条双向的ea/2+eb/2+ec的边。

  这样连边就能满足第二条性质了,反正就是脑补一下各种割法,就发现它奥妙重重,十分正确。

  然后可以缩一下边,把s->i的边集以及i->t的合并一下[优化一下常数]。

#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; const int maxn=;
const int maxm=;
const int INF=0x3f3f3f3f; struct Node{
int data,next,low;
}node[maxm*+maxn*]; #define now node[point].data
#define www node[point].low
#define then node[point].next int n,m,cnt;
int s,t,ans;
int wa[maxn],wb[maxn];
int stoi[maxn],itot[maxn];
int cur[maxn],head[maxn];
int dis[maxn],que[maxn]; void add(int u,int v,int w){
node[cnt].data=v;node[cnt].next=head[u];node[cnt].low=w;head[u]=cnt++;
node[cnt].data=u;node[cnt].next=head[v];node[cnt].low=;head[v]=cnt++;
} void add2(int u,int v,int w){
node[cnt].data=v;node[cnt].next=head[u];node[cnt].low=w;head[u]=cnt++;
node[cnt].data=u;node[cnt].next=head[v];node[cnt].low=w;head[v]=cnt++;
} bool BFS(){
memset(dis,-,sizeof(dis));
int H=,T=;que[]=s;dis[s]=;
while(H<T){
H++;
for(int point=head[que[H]];point!=-;point=then)
if(www && dis[now]<){
dis[now]=dis[que[H]]+;
que[++T]=now;
}
}
return dis[t]>;
} int dfs(int x,int low){
if(x==t) return low;
int Low;
for(int &point=cur[x];point!=-;point=then)
if(www && dis[now]==dis[x]+){
Low=dfs(now,min(low,www));
if(Low){
www-=Low,node[point^].low+=Low;
return Low;
}
}
return ;
} int main(){
#ifndef ONLINE_JUDGE
freopen("3511.in","r",stdin);
freopen("3511.out","w",stdout);
#endif int u,v,Ea,Eb,Ec; scanf("%d%d",&n,&m);
t=n+;
for(int i=s;i<=t;i++) head[i]=-;
for(int i=;i<n;i++) scanf("%d",&wa[i]),stoi[i]+=(wa[i]<<);
for(int i=;i<n;i++) scanf("%d",&wb[i]),itot[i]+=(wb[i]<<);
for(int i=;i<=m;i++){
scanf("%d%d%d%d%d",&u,&v,&Ea,&Eb,&Ec);
add2(u,v,Ea+Eb+(Ec<<));
stoi[u]+=Ea,stoi[v]+=Ea;
itot[u]+=Eb,itot[v]+=Eb;
}
for(int i=;i<=n;i++)
ans+=stoi[i]+itot[i];
stoi[]=itot[n]=INF;
for(int i=;i<=n;i++)
add(s,i,stoi[i]),add(i,t,itot[i]); int flag;
while(BFS()){
memcpy(cur,head,sizeof(head));
while(flag=dfs(s,INF))
ans-=flag;
} ans>>=;
printf("%d",ans);
return ;
}

最新文章

  1. 重新走过HTML,那些让我amazing 的标签
  2. 简单实用的Log4net帮助类
  3. java 生产者消费者问题 并发问题的解决
  4. Linux rsync 命令详解
  5. VC++编译libpng
  6. ios 聊天demo 和nsoperationdemo
  7. (转)HTML5游戏如何挣钱?2条经验让你每款赚3万刀
  8. Linux内核设计与实现 读书笔记
  9. java Runtime类
  10. JavaScript的DOM编程--04--获取元素节点的子节点
  11. github学习(三)
  12. java之Spring(AOP)-Annotation实现添加切面
  13. java中的try-catch-finally异常处理(学习笔记)
  14. 使用 Jira 和 Confluence 6 在一起
  15. To the Max POJ - 1050 (最大子段和)
  16. 千行代码入门Python
  17. python第四天 三级菜单新思路
  18. dubbo框架原理
  19. 4、redis之使用commons-pool
  20. flush()的原理

热门文章

  1. css3动画响应式404页面
  2. C# Async与Await用法
  3. Cassandra 技术选型的问题
  4. Discuz X3.2 分区 gid 完美伪静态方法 Apache/Nginx
  5. 【转】操作ini文件
  6. cxGrid使用汇总(一)
  7. 限制&lt;input&gt;输入内容 只允许数字 或者 字母
  8. WCF全面解析第一章 WCF 简介
  9. openstack命令
  10. 在WPF程序中将控件所呈现的内容保存成图像(转载)