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

3 4 2
0 1 1
1 2 1
2 3 100
0 3 1

Sample Output

3
【样例说明】
小智和小霞一起前去营救皮卡丘。在最优方案中,小智先从真新镇前往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,费用流)的更多相关文章

  1. BZOJ 2324: [ZJOI2011]营救皮卡丘( floyd + 费用流 )

    昨晚写的题...补发一下题解... 把1~N每个点拆成xi, yi 2个. 预处理i->j经过编号不超过max(i,j)的最短路(floyd) S->0(K, 0), S->xi(1 ...

  2. BZOJ2324 [ZJOI2011]营救皮卡丘 【费用流】

    题目 皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路. 火箭队一共有N个据点,据点之间存在M条双向道 ...

  3. BZOJ 2324: [ZJOI2011]营救皮卡丘(带上下限的最小费用最大流)

    这道题么= =还是有些恶心的,第一次写带上下界的网络流,整个人都萌萌哒~~~ 首先先预处理得最短路后 直接用费用流做就行了。 第一次写,还是挺好写的= = CODE: #include<cstd ...

  4. bzoj 2324: [ZJOI2011]营救皮卡丘

    #include<cstdio> #include<iostream> #include<cstring> #include<cmath> #inclu ...

  5. 【洛谷P4542】 [ZJOI2011]营救皮卡丘(费用流)

    洛谷 题意: 给出\(n\)个点,\(m\)条边,现在有\(k,k\leq 10\)个人从\(0\)号点出发前往\(n\)点. 规定若某个人想要到达\(x\)点,则\(1\)~\(x-1\)号点都有人 ...

  6. BZOJ.2324.[ZJOI2011]营救皮卡丘(费用流 Floyd)

    BZOJ 洛谷 首先预处理出\(dis[i][j]\),表示从\(i\)到\(j\)的最短路.可以用\(Floyd\)处理. 注意\(i,j\)是没有大小关系限制的(\(i>j\)的\(dis[ ...

  7. 【洛谷 P4542】 [ZJOI2011]营救皮卡丘(费用流)

    题目链接 用最多经过\(k\)条经过\(0\)的路径覆盖所有点. 定义\(ds[i][j]\)表示从\(i\)到\(j\)不经过大于\(max(i,j)\)的点的最短路,显然可以用弗洛伊德求. 然后每 ...

  8. bzoj 2324 ZJOI 营救皮卡丘 费用流

    题的大概意思就是给定一个无向图,边有权值,现在你有k个人在0点,要求走到n点,且满足 1:人们可以分头行动,可以停在某一点不走了 2:当你走到x时,前x-1个点必须全部走过(不同的人走过也行,即分两路 ...

  9. BZOJ-2324 营救皮卡丘 最小费用可行流+拆下界+Floyd预处理

    准备一周多的期末,各种爆炸,回来后状态下滑巨快...调了一晚上+80%下午 2324: [ZJOI2011]营救皮卡丘 Time Limit: 10 Sec Memory Limit: 256 MB ...

随机推荐

  1. 期权交易基本原理——买进看跌期权(Long Put),卖出看跌期权(Short Put)

    期权交易基本原理--买进看跌期权(Long Put),卖出看跌期权(Short Put) 来源:中电投先融期货-青岛 浏览:13508次2014-07-25 14:25:55 3 第三节 买进看跌期权 ...

  2. BZOJ 1668: [Usaco2006 Oct]Cow Pie Treasures 馅饼里的财富

    Description 最近,奶牛们热衷于把金币包在面粉里,然后把它们烤成馅饼.第i块馅饼中含有Ni(1<=Ni<=25)块金币,并且,这个数字被醒目地标记在馅饼表面. 奶牛们把所有烤好的 ...

  3. Spring MVC中使用Mongodb总结

    近期项目做了次架构调整,原来是使用MySQL+GeoHash来存储LBS数据(地理位置信息),现在使用NOSQL数据库MongoDB来存储LBS数据(地理位置信息).由于项目是基于spring MVC ...

  4. Struts 2 初学的复习巩固

    Q:使用Struts2 开发程序的基本步骤? A: 1)加载Struts2类库: 2)配置web.xml文件,定义核心Filter来拦截用户请求: 3)开发视图层页面,即JSP页面: 4)定义处理用户 ...

  5. JavaScript中的数组对象遍历、读写、排序等操作

    以百度前端技术学院的js任务三为例,复习一下关于js数组的几个点 题目 <!DOCTYPE> <html> <head> <meta charset=&quo ...

  6. IndentityServer4

    官网: https://identityserver4.readthedocs.io/en/latest/index.html 比较好的中文博客: 晓晨Master: https://www.cnbl ...

  7. Chapter 4 Invitations——27

    "Myself, obviously." He enunciated every syllable, as if he were talking to someone mental ...

  8. eayUi panel实现上一页下一页

    function 是为了第一次加载的时候显示页面 butt1和butt2触发上一页下一页,后面绑定参数即可 问题:.panel({href:href})到后台的时候会请求两次,这个问题还没有解决 把 ...

  9. Codeforces Round #499 (Div. 2) C. Fly(数学+思维模拟)

    C. Fly time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  10. RocketMQ专题1:入门

    RocketMQ入门 源码和应用下载 ​ 这里以RocketMQ的4.3.0版本为例,本地环境为windows10,jdk1.8, maven3.2.1. 源码下载地址: http://mirrors ...