bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)
2324: [ZJOI2011]营救皮卡丘
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 1777 Solved: 712
[Submit][Status][Discuss]
Description
皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路。
火箭队一共有N个据点,据点之间存在M条双向道路。据点分别从1到N标号。小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘。为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点。
由于火箭队的重重布防,要想摧毁K号据点,必须按照顺序先摧毁1到K-1号据点,并且,如果K-1号据点没有被摧毁,由于防御的连锁性,小智一行任何一个人进入据点K,都会被发现,并产生严重后果。因此,在K-1号据点被摧毁之前,任何人是不能够经过K号据点的。
为了简化问题,我们忽略战斗环节,小智一行任何一个人经过K号据点即认为K号据点被摧毁。被摧毁的据点依然是可以被经过的。
K个人是可以分头行动的,只要有任何一个人在K-1号据点被摧毁之后,经过K号据点,K号据点就被摧毁了。显然的,只要N号据点被摧毁,皮卡丘就得救了。
野外的道路是不安全的,因此小智一行希望在摧毁N号据点救出皮卡丘的同时,使得K个人所经过的道路的长度总和最少。
请你帮助小智设计一个最佳的营救方案吧!
Input
第一行包含三个正整数N,M,K。表示一共有N+1个据点,分别从0到N编号,以及M条无向边。一开始小智一行共K个人均位于0号点。
接下来M行,每行三个非负整数,第i行的整数为Ai,Bi,Li。表示存在一条从Ai号据点到Bi号据点的长度为Li的道路。
Output
仅包含一个整数S,为营救皮卡丘所需要经过的最小的道路总和。
Sample Input
0 1 1
1 2 1
2 3 100
0 3 1
Sample Output
【样例说明】
小智和小霞一起前去营救皮卡丘。在最优方案中,小智先从真新镇前往1号点,接着前往2号据点。当小智成功摧毁2号据点之后,小霞从真新镇出发直接前往3号据点,救出皮卡丘。
HINT
对于100%的数据满足N ≤ 150, M ≤ 20 000, 1 ≤ K ≤ 10, Li ≤ 10 000, 保证小智一行一定能够救出皮卡丘。至于为什么K ≤ 10,你可以认为最终在小智的号召下,小智,小霞,小刚,小建,小遥,小胜,小光,艾莉丝,天桐,还有去日本旅游的黑猫警长,一同前去大战火箭队。
Source
【思路】
Floyd+费用流。
题目条件:1 每个点都必须经过 , 2 经过j时必须已经经过了0..j-1
利用floyd求出对点之间的最短距,转化为DAG即保证条件2。求DAG上至多不超过k条的覆盖路。
构图:每个点建立XY结点,连边(S,0,K,0)(S,Xi,1,0)(Yi,T,1,0),如果DAG上i,j之间有边,则连边(Xi,Yj,1,d[i][j])。
【代码】
- #include<cstdio>
- #include<cstring>
- #include<queue>
- #include<vector>
- #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
- using namespace std;
- typedef long long LL ;
- const int maxn = +;
- const int INF = 1e9;
- struct Edge{ int u,v,cap,flow,cost;
- };
- struct zkw {
- int n,m,s,t;
- int vis[maxn],d[maxn];
- vector<int> G[maxn];
- vector<Edge> es;
- void init(int n) {
- this->n=n;
- es.clear();
- for(int i=;i<n;i++) G[i].clear();
- }
- void AddEdge(int u,int v,int cap,int cost) {
- es.push_back((Edge){u,v,cap,,cost});
- es.push_back((Edge){v,u,,,-cost});
- m=es.size();
- G[u].push_back(m-);
- G[v].push_back(m-);
- }
- bool spfa() {
- memset(vis,,sizeof(vis));
- for(int i=;i<n;i++) d[i]=INF;
- queue<int> q;
- d[t]= , vis[t]= , q.push(t);
- while(!q.empty()) {
- int u=q.front(); q.pop() , vis[u]=;
- for(int i=;i<G[u].size();i++) {
- Edge& e=es[G[u][i]];
- int v=e.v;
- if(es[G[u][i]^].cap && d[v]>d[u]-e.cost) {
- d[v]=d[u]-e.cost;
- if(!vis[v]) {
- vis[v]=;
- q.push(v);
- }
- }
- }
- }
- return d[s]!=INF;
- }
- int dfs(int u,int a,LL& cost) {
- vis[u]=; if(u==t) return a;
- int used=,w;
- for(int i=;i<G[u].size();i++) {
- Edge& e=es[G[u][i]];
- int v=e.v;
- if(d[u]-e.cost==d[v] && !vis[v] && e.cap) {
- w=dfs(v,min(a-used,e.cap),cost);
- cost+=w*e.cost;
- e.cap-=w , es[G[u][i]^].cap+=w;
- used+=w; if(used==a) return a;
- }
- }
- return used;
- }
- int Mincost(int s,int t,LL& cost) {
- this->s=s , this->t=t;
- int flow=; cost=;
- while(spfa()) {
- vis[t]=;
- while(vis[t]) {
- memset(vis,,sizeof(vis));
- flow+=dfs(s,INF,cost);
- }
- }
- return flow;
- }
- } mc;
- int n,m,K;
- int d[maxn][maxn];
- int main() {
- scanf("%d%d%d",&n,&m,&K);
- mc.init(n+n+);
- int s=n+n+,t=s+;
- int u,v,w;
- FOR(i,,n) FOR(j,,n) d[i][j]=INF;
- FOR(i,,m) {
- scanf("%d%d%d",&u,&v,&w);
- d[u][v]=d[v][u]=min(d[u][v],w); //重边
- }
- FOR(k,,n) FOR(i,,n) FOR(j,,n)
- if(k<=j || k<=i) d[i][j]=min(d[i][k]+d[k][j],d[i][j]);
- mc.AddEdge(s,n+,K,);
- FOR(i,,n) {
- mc.AddEdge(s,i+n+,,);
- mc.AddEdge(i,t,,);
- }
- FOR(i,,n) FOR(j,i+,n)
- if(d[i][j]!=INF) mc.AddEdge(i+n+,j,,d[i][j]);
- LL cost;
- mc.Mincost(s,t,cost);
- printf("%lld",cost);
- return ;
- }
bzoj 2324 [ZJOI2011]营救皮卡丘(floyd,费用流)的更多相关文章
- BZOJ 2324: [ZJOI2011]营救皮卡丘( floyd + 费用流 )
昨晚写的题...补发一下题解... 把1~N每个点拆成xi, yi 2个. 预处理i->j经过编号不超过max(i,j)的最短路(floyd) S->0(K, 0), S->xi(1 ...
- BZOJ2324 [ZJOI2011]营救皮卡丘 【费用流】
题目 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路. 火箭队一共有N个据点,据点之间存在M条双向道 ...
- BZOJ 2324: [ZJOI2011]营救皮卡丘(带上下限的最小费用最大流)
这道题么= =还是有些恶心的,第一次写带上下界的网络流,整个人都萌萌哒~~~ 首先先预处理得最短路后 直接用费用流做就行了。 第一次写,还是挺好写的= = CODE: #include<cstd ...
- bzoj 2324: [ZJOI2011]营救皮卡丘
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> #inclu ...
- 【洛谷P4542】 [ZJOI2011]营救皮卡丘(费用流)
洛谷 题意: 给出\(n\)个点,\(m\)条边,现在有\(k,k\leq 10\)个人从\(0\)号点出发前往\(n\)点. 规定若某个人想要到达\(x\)点,则\(1\)~\(x-1\)号点都有人 ...
- BZOJ.2324.[ZJOI2011]营救皮卡丘(费用流 Floyd)
BZOJ 洛谷 首先预处理出\(dis[i][j]\),表示从\(i\)到\(j\)的最短路.可以用\(Floyd\)处理. 注意\(i,j\)是没有大小关系限制的(\(i>j\)的\(dis[ ...
- 【洛谷 P4542】 [ZJOI2011]营救皮卡丘(费用流)
题目链接 用最多经过\(k\)条经过\(0\)的路径覆盖所有点. 定义\(ds[i][j]\)表示从\(i\)到\(j\)不经过大于\(max(i,j)\)的点的最短路,显然可以用弗洛伊德求. 然后每 ...
- bzoj 2324 ZJOI 营救皮卡丘 费用流
题的大概意思就是给定一个无向图,边有权值,现在你有k个人在0点,要求走到n点,且满足 1:人们可以分头行动,可以停在某一点不走了 2:当你走到x时,前x-1个点必须全部走过(不同的人走过也行,即分两路 ...
- P4542-[ZJOI2011]营救皮卡丘【费用流,Floyd】
正题 题目链接:https://www.luogu.com.cn/problem/P4542 题目大意 给出\(n+1\)个点\(m\)条边的无向图,\(k\)个人开始在\(0\)号点,一个人进入\( ...
随机推荐
- "库未注册"(Library not registered)异常.
启发链接:http://social.msdn.microsoft.com/Forums/vstudio/en-US/f25b80bc-ecd4-4c37-8be3-9106a765b072/libr ...
- SQL SERVER 存储过程基础
一.注释 -- 单行注释,从这到本行结束为注释,类似C++,c#中// /* … */ 多行注释,类似C++,C#中/* … */ 二.变量 (int, smallint, tinyint, deci ...
- iOS 里面如何使用第三方应用程序打开自己的文件,调用wps其他应用打开当前应用里面的的ppt doc xls
我们的自己的应用里面经常涉及的要打开ppt doc,这样的功能,以前总以为iOS沙盒封闭化,不可能实现,后来终于解决了 使用 UIDocumentInteractionController 来解决这一 ...
- ios里面如何压缩图片
在iOS里面,压缩图片跟在其他环境里面差不多,都和累死, 就是对当前图片从新画图,制定一个尺寸的问题 UIImage* image = [UIImage imageNamed:@"cat.j ...
- WampServer修改端口及菜单Localhost
一.修改Apache端口 1.在界面中选Apache,弹出隐藏菜单选项,打开配置文件httpd.conf: 2.找到 Listen 80: 3.将 80 改成 8080(当然自己也可以设定别的不使用的 ...
- I/O多路转接之select
系统提供select函数来实现多路复⽤用输入/输出模型.select系统调用是用来让我们的程序监视 多个文件句柄的状态变化的.程序会停在select这里等待,直到被监视的文件句柄有一个或 多个发生了状 ...
- Windows程序设计 贪吃蛇c
看Windows程序有段时间了,终于动手写东西.贪吃蛇算是一个开始吧,下面的贪吃蛇很简单,也有很多地方需要修改,还有情况没有考虑QAQ 但这不是我的目的了... 思路很简单:建个链表储存蛇身节点即可. ...
- .getBoundingClientRect()
.getBoundingClientRect() 该方法获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置,他返回的是一个对象,即Object,该对象有4个属性:top,left,right, ...
- PHP常用代码段:
1.PHP加密解密 function encryptDecrypt($key, $string, $decrypt){ if($decrypt){ $decrypted ...
- php基于数组的分页实现
关于数组的分页函数,用数组进行分页的好处是可以方便的进行联合多表查询,只需要将查询的结果放在数组中就可以了以下是数组分页的函数,函数page_array用于数组的分页,函数show_array用于分页 ...