準備一周多的期末,各種爆炸,回來后狀態下滑巨快。。。調了一晚上+80%下午
2324: [ZJOI2011]營救皮卡丘 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 1839 Solved: 735 [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 Day2
首先此題需要滿足一些條件: 1.到X點之前前X-1個點必須都經過 2.人數出發的人數小于等于K 3.總路程最小
分析過后,兩點間的距離,肯定是路徑的費用,那么應該用連通性和路徑的容量來限制其它的條件;
建圖: 每個點拆出一個下界(i和i’) 1.S–>0 容量為k,費用為0 2.i–>T 容量為1,費用為0 3.i’–>j 容量為1,費用為d【i】【j】 4.S–>i’ 容量為1,費用為0
在連邊前跑一遍Floyd,找出兩點的最短路徑,不過中間點k必須不大于i或j。
此題讀入有重邊,注意處理一下即可。
下面是代碼:(PS調了很久。。。還shabi了點。。) PS:程序中0點的標號為n+1,i’的標號為i+n+1
using namespace std;
struct data{
int c,to,
next ,v;
}edge[
100010 ];
int head[
100010 ],cnt=
1 ;
int n,
m ,k;
int dis[
100010 ];
bool visit[
100010 ];
int q[100010] ,h,t;
int S,T;
bool mark[
100010 ];
int d[
200 ][
200 ];
int ans=
0 ;
int read ()
{
int x =
0 ,f=
1 ;char ch=getchar();
while (ch<
'0' || ch>
'9' ) {
if (ch==
'-' ) f=-
1 ; ch=getchar();}
while (ch>=
'0' && ch<=
'9' ) {
x =
x *10 +ch-
48 ; ch=getchar();}
return x *f ;
}void add(
int u,
int v,
int cap,
int cost)
{cnt++;edge[cnt].
next =head[u];edge[cnt].to=v;edge[cnt].v=cap;edge[cnt].c=cost;head[u]=cnt;
}void insert(
int u,
int v,
int cap,
int cost)
{add(u,v,cap,cost);add(v,u,
0 ,-cost);
}void init()
{n=
read ();
m =
read ();k=
read ();
for (
int i=
0 ; i<=n; i++)
for (
int j=
0 ; j<=n; j++)
if (i==j) d[i][j]=
0 ;
else d[i][j]=inf;
for (
int i=
1 ; i<=
m ; i++){
int u=
read (),v=
read (),l=
read ();d[u][v]=d[v][u]=min(d[u][v],l);}
}void floyd()
{
for (
int l=
0 ; l<=n; l++)
for (
int i=
0 ; i<=n; i++)
for (
int j=
0 ; j<=n; j++)
if ((l<=i || l<=j) && d[i][j]>d[i][l]+d[l][j])d[i][j]=d[i][l]+d[l][j];
}void make()
{floyd(); S=
2 *n +
2 ;T=
2 *n +
3 ;
for (
int i=
1 ; i<=n; i++){insert(S,i+n+
1 ,
1 ,
0 );insert(i,T,
1 ,
0 );}insert(S,
1 +n,k,
0 );
for (
int i=
0 ; i<=n; i++)
for (
int j=i+
1 ; j<=n; j++)
if (d[i][j]!=inf)insert(i+n+
1 ,j,
1 ,d[i][j]);
}bool spfa()
{memset(visit,
0 ,sizeof(visit));
for (
int i=
0 ; i<=T; i++) dis[i]=inf;h=
0 ,t=
1 ;
q[0] =T;dis[T]=
0 ;visit[T]=
1 ;
while (h<t){
int now=
q[h] ;h++;
for (
int i=head[now]; i; i=edge[i].
next )
if (edge[i^
1 ].v && dis[now]-edge[i].c<dis[edge[i].to]){dis[edge[i].to]=dis[now]-edge[i].c;
if (!visit[edge[i].to]){
q[t++] =edge[i].to;visit[edge[i].to]=
1 ;}}visit[now]=
0 ;}
return dis[S]!=inf;
}
int dfs(
int loc,
int low)
{mark[loc]=
1 ;
if (loc==T)
return low;
int w,used=
0 ;
for (
int i=head[loc]; i; i=edge[i].
next )
if (edge[i].v && !mark[edge[i].to] && dis[edge[i].to]==dis[loc]-edge[i].c){w=dfs(edge[i].to,min(low-used,edge[i].v));ans+=w
*edge [i].c;used+=w;edge[i].v-=w;edge[i^
1 ].v+=w;
if (used==low)
return low;}
return used;
}void zkw()
{
int tmp=
0 ;
while (spfa()){mark[T]=
1 ;
while (mark[T]){memset(mark,
0 ,sizeof(mark));tmp+=dfs(S,inf);}}
}
int main()
{init();make();zkw();
printf (
"%d " ,ans);
return 0 ;
}
轉載于:https://www.cnblogs.com/DaD3zZ-Beyonder/p/5346221.html
與50位技術專家面對面 20年技術見證,附贈技術全景圖
總結
以上是生活随笔 為你收集整理的BZOJ-2324 营救皮卡丘 最小费用可行流+拆下界+Floyd预处理 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。