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. python学习笔记(二)

    (一)模块打包     --->        注:suba和subb文件夹下的__init__.py文件,即使为空,也必须存在 "setup.py" from distut ...

  2. NOIP提高组2010 关押罪犯

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用“怨气值”(一个正整数值)来表示 ...

  3. BIP_开发案例05_BI Pubisher标准做法以BIP.XML为数据源以BIP.RTF为模板的简单例子(案例)

    2014-05-31 Created By BaoXinjian

  4. 【AngularJS】AngularJS 教程

    AngularJS通过新的属性和表达式扩展了HTML.------------->扩展HTML属性 AngularJS可以构建一个单页面应用程序(SPAs: Single Page Applic ...

  5. TS数据结构分析

    1.TS包得数据结构 2. // Transport packet headertypedef struct TS_packet_header{    unsigned sync_byte       ...

  6. 文件处理-Directory类 (C#)

    转http://skybirdzw.blog.163.com/blog/static/7257062620099751329403/ 文件处理-Directory类 (C#) Directory.Cr ...

  7. Hibernate 配置派生属性

    在持久化类中,有些属性在表中没有对应的字段,可以在映射文件中设置派生属性. 比如在一个订单中有多个商品的价格,但没有计算总的价格,可以在持久化类中增添一个统计总价格的属性,在映射文件中配置一些信息. ...

  8. C#网络程序设计(3)网络传输编程之TCP编程

        网络传输编程指基于各种网络协议进行编程,包括TCP编程,UDP编程,P2P编程.本节介绍TCP编程.     (1)TCP简介: TCP是TCP/IP体系中最重要的传输层协议,它提供全双工和可 ...

  9. 【消灭代办】第1周 - 敏感词判断、图片206、parseInt

    11.16代办一:[敏感词判断] 代办描述: 一堆字符串组成的数组,给你一个字符串,让你去查找这个字符串是否在这个数组当中? 关键考点: 数组匹配,看一个数组中有没有这个字符串. 解决思路: 遍历数组 ...

  10. java List集合中contains方法总是返回false

    ArrayList的contains方法 java 今天在用ArrayList类的caontains方法是遇到了问题,我写了一个存放User类的ArrayList 但在调用list.contains( ...