【BZOJ3691】游行

Description

每年春季,在某岛屿上都会举行游行活动。
在这个岛屿上有N个城市,M条连接着城市的有向道路。
你要安排英雄们的巡游。英雄从城市si出发,经过若干个城市,到城市ti结束,需要特别注意的是,每个英雄的巡游的si可以和ti相同,但是必须至少途径2个城市。
每次游行你的花费将由3部分构成:
1.每个英雄游行经过的距离之和,需要特别注意的是,假如一条边被途径了k次,那么它对答案的贡献是k*ci,ci表示这条边的边权。
2.如果一个英雄的巡游的si不等于ti,那么会额外增加C的费用。因为英雄要打的回到起点。
3.如果一个城市没有任何一个英雄途经,那么这个城市会很不高兴,需要C费用的补偿。
你有无数个的英雄。你要合理安排游行方案,使得费用最小。
由于每年,C值都是不一样的。所以你要回答Q个询问,每个询问都是,当C为当前输入数值的时候的答案。

Input

第一行正整数N,M,Q;
接下来的M行,每行ai,bi,ci,表示有一条从ai到bi,边权为ci的有向道路。保证不会有自环,但不保证没有重边。
接下来Q行,每行一个C,表示询问当每次费用为C时的最小答案。

Output

Q行,每行代表一个询问的答案。

Sample Input

6 5 3
1 3 2
2 3 2
3 4 2
4 5 2
4 6 2
1
5
10

Sample Output

6
21
32

HINT

【样例说明】
第一年的时候,C只有1。我们比较懒所以就不安排英雄出游了,需要支付6的费用。
第二年的时候,我们可以这么安排:
第一个英雄1->3->4->5,需要付2+2+2=6的费用,同时还要花5费用打的回家。再花5+5的费用来补偿2号城市和6号城市。
第三年略。

【数据范围】
对于100%的数据,2<=N<=250,1<=M<=30000,1<=Q<=10000。
1<=ci<=10000,1<=C<=10000。

题解:比较难的费用流建模题。

首先由于每次的C不同,我们建的图中是不能包含C这个东西的,但是C的代价怎么算呢?我们可以将题意理解为:选择若干条路径<a,b>(a!=b),每条路径只覆盖路径的终点,最后所有没被覆盖的点都要付出C的代价。回忆最小覆盖的方法,我们拆点建出图:

先跑floyd得到任意两点间的最短路dis(a,b)(a!=b),然后:

1.a  -> b' 容量1,费用dis(a,b)
2.S  -> a  容量1,费用0
3.a' -> T  容量1,费用0
那么我们跑费用流的时候,每增广一次,就用当前的 costflow+C*没被覆盖的点数 更新答案即可。

但是这样还是不能通过此题,不过我们发现,每增广一次所需要的费用是不断增大的,也就意味着存在一个时刻,使得之前每增广一次的费用都小于等于C,之后的每次增广的费用都大于C。所以我们可以记录下每次增广需要的费用,存到数组里,查询时二分一下即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
int n,m,Q,tot,S,T,cnt;
int head[1000],dis[1000],pv[1000],pe[1000],to[1000000],next[1000000],cost[1000000],flow[1000000],val[1000],inq[1000];
int s[1000],map[300][300];
queue<int> q;
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
inline void add(int a,int b,int c,int d)
{
to[cnt]=b,cost[cnt]=c,flow[cnt]=d,next[cnt]=head[a],head[a]=cnt++;
to[cnt]=a,cost[cnt]=-c,flow[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
}
int bfs()
{
memset(dis,0x3f,sizeof(dis));
q.push(S),dis[S]=0;
int i,u;
while(!q.empty())
{
u=q.front(),q.pop(),inq[u]=0;
for(i=head[u];i!=-1;i=next[i]) if(flow[i]&&dis[to[i]]>dis[u]+cost[i])
{
dis[to[i]]=dis[u]+cost[i],pe[to[i]]=i,pv[to[i]]=u;
if(!inq[to[i]]) inq[to[i]]=1,q.push(to[i]);
}
}
return dis[T]<0x3f3f3f3f;
}
int main()
{
n=rd(),m=rd(),Q=rd(),S=0,T=2*n+1;
memset(head,-1,sizeof(head));
int i,j,k,a,b,c,l,r,mid;
memset(map,0x3f,sizeof(map));
for(i=1;i<=n;i++) map[i][i]=0;
for(i=1;i<=m;i++) a=rd(),b=rd(),c=rd(),map[a][b]=min(map[a][b],c);
for(k=1;k<=n;k++) for(i=1;i<=n;i++) for(j=1;j<=n;j++) map[i][j]=min(map[i][j],map[i][k]+map[k][j]);
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j) add(i,j+n,map[i][j],1);
for(i=1;i<=n;i++) add(S,i,0,1),add(i+n,T,0,1);
while(bfs())
{
val[++tot]=dis[T],s[tot]=s[tot-1]+val[tot];
for(i=T;i!=S;i=pv[i]) flow[pe[i]]--,flow[pe[i]^1]++;
}
for(i=1;i<=Q;i++)
{
a=rd(),l=0,r=tot+1;
while(l<r)
{
mid=(l+r)>>1;
if(val[mid]<a) l=mid+1;
else r=mid;
}
printf("%d\n",s[l-1]+(n-l+1)*a);
}
return 0;
}

【BZOJ3691】游行 费用流的更多相关文章

  1. hdu-5988 Coding Contest(费用流)

    题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Ot ...

  2. POJ2195 Going Home[费用流|二分图最大权匹配]

    Going Home Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 22088   Accepted: 11155 Desc ...

  3. BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

    3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 960  Solved: 5 ...

  4. 洛谷 1004 dp或最大费用流

    思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...

  5. Codeforces 730I [费用流]

    /* 不要低头,不要放弃,不要气馁,不要慌张 题意: 给两行n个数,要求从第一行选取a个数,第二行选取b个数使得这些数加起来和最大. 限制条件是第一行选取了某个数的条件下,第二行不能选取对应位置的数. ...

  6. zkw费用流+当前弧优化

    zkw费用流+当前弧优化 var o,v:..] of boolean; f,s,d,dis:..] of longint; next,p,c,w:..] of longint; i,j,k,l,y, ...

  7. 【BZOJ-4213】贪吃蛇 有上下界的费用流

    4213: 贪吃蛇 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 58  Solved: 24[Submit][Status][Discuss] Desc ...

  8. 【BZOJ-3638&3272&3267&3502】k-Maximum Subsequence Sum 费用流构图 + 线段树手动增广

    3638: Cf172 k-Maximum Subsequence Sum Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 174  Solved: 9 ...

  9. [bzoj4514]数字配对[费用流]

    今年SDOI的题,看到他们在做,看到过了一百多个人,然后就被虐惨啦... 果然考试的时候还是打不了高端算法,调了...几天 默默地yy了一个费用流构图: 源连所有点,配对的点连啊,所有点连汇... 后 ...

随机推荐

  1. php 区分0和空

    能够区分出来的有2,4,6 方法 public function test(){ $test=; if($test==''){ echo '<br />在php中1,0即为空'; //被输 ...

  2. Thinkphp5笔记六:公共模块common的使用

    common模块属于公共模块,Thinkphp框架,默认就能调用. 实际用处:任何模块都可能用到的模型.控制.事件提取出来放到公共模块下. 一.公共事件  apps\common\common.php ...

  3. (转)GCT之逻辑经验总结(拿来主义)

    GCT逻辑考试,并非考核逻辑专业知识,而是考核考生的日常逻辑思维能力.应该说日常逻辑思维能力是人在成长过程中及在社会活动中形成的,因此,只要运用好这种能力,就能取得逻辑考试的好成绩.因此可以认为:GC ...

  4. UNIX环境编程学习笔记(9)——文件I/O之文件访问权限的屏蔽和更改

    lienhua342014-09-10 1 文件访问权限 在文件访问权限和进程访问控制中,我们已经讲述过文件访问权限位,为了方便,我们重新列在下面, 表 1: 文件的 9 个访问权限位  st_mod ...

  5. 《Thinking in Java》习题——吸血鬼数字

    最近在看<Java编程思想>,这本书非常棒,不愧是Java程序员的圣经.看到第四章,后面有道题目很有意思,于是就自己做了做.

  6. Nine-patch

    http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch   This NinePatch defi ...

  7. struts2防止反复提交的办法

    <? xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC " ...

  8. cordova开发ios炸鸡

    cordova/lib/copy-www-build-step.sh: Permission denied 解决办法: cd platforms/ios/cordova/lib sudo chmod ...

  9. Centos6.3 下使用 Tomcat-6.0.43 非root用户 部署 生产环境 端口转发方式

    一.安装JDK环境 方法一. 官方下载链接 http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260 ...

  10. Android系统启动流程

    当系统引导程序启动Linux内核,内核会记载各种数据结构,和驱动程序,加载完毕之后,Android系统开始启动并加载第一个用户级别的进程:init(system/core/init/Init.c) 查 ...