bzoj2324 [ZJOI2011]营救皮卡丘 费用流

 [ZJOI2011]营救皮卡丘

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 2653  Solved: 1101
[Submit][Status][Discuss]

Description

皮卡丘被火箭队用邪恶的计谋抢走了!这三个坏家伙还给小智留下了赤果果的挑衅!为了皮卡丘,也为了正义,小智和他的朋友们义不容辞的踏上了营救皮卡丘的道路。

火箭队一共有N个据点,据点之间存在M条双向道路。据点分别从1N标号。小智一行K人从真新镇出发,营救被困在N号据点的皮卡丘。为了方便起见,我们将真新镇视为0号据点,一开始K个人都在0号点。

由于火箭队的重重布防,要想摧毁K号据点,必须按照顺序先摧毁1K-1号据点,并且,如果K-1号据点没有被摧毁,由于防御的连锁性,小智一行任何一个人进入据点K,都会被发现,并产生严重后果。因此,在K-1号据点被摧毁之前,任何人是不能够经过K号据点的。

为了简化问题,我们忽略战斗环节,小智一行任何一个人经过K号据点即认为K号据点被摧毁。被摧毁的据点依然是可以被经过的。

K个人是可以分头行动的,只要有任何一个人在K-1号据点被摧毁之后,经过K号据点,K号据点就被摧毁了。显然的,只要N号据点被摧毁,皮卡丘就得救了。

野外的道路是不安全的,因此小智一行希望在摧毁N号据点救出皮卡丘的同时,使得K个人所经过的道路的长度总和最少。

请你帮助小智设计一个最佳的营救方案吧!

 

Input

第一行包含三个正整数N,M,K。表示一共有N+1个据点,分别从0N编号,以及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

 

题解:https://www.cnblogs.com/liu-runda/p/6294382.html

  1 #include<cstring>
  2 #include<cmath>
  3 #include<algorithm>
  4 #include<iostream>
  5 #include<cstdio>
  6 #include<queue>
  7 
  8 #define inf 1000000007
  9 #define M 100007
 10 #define N 307
 11 #define ll long long
 12 using namespace std;
 13 inline int read()
 14 {
 15     int x=0,f=1;char ch=getchar();
 16     while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();}
 17     while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
 18     return x*f;
 19 }
 20 
 21 int n,m,k,S,T;
 22 int a[N][N];
 23 int cnt=1,hed[N],nxt[M],rea[M],val[M],cost[M];
 24 int dis[N],flag[N];
 25 struct Node
 26 {
 27     int e,fa;
 28     void init(){e=fa=-1;}
 29 }pre[N];
 30 
 31 void Floyd()
 32 {
 33     for (int k=0;k<=n;k++)
 34         for (int i=0;i<=n;i++)
 35             for (int j=0;j<=n;j++)
 36                 if (k<=i||k<=j) a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
 37 }
 38 void add(int u,int v,int x,int y)
 39 {
 40     nxt[++cnt]=hed[u];
 41     hed[u]=cnt;
 42     rea[cnt]=v;
 43     val[cnt]=x;
 44     cost[cnt]=y;
 45 }
 46 bool Spfa()
 47 {
 48     for (int i=0;i<=T;i++)
 49     {
 50         flag[i]=0;
 51         dis[i]=inf;
 52         pre[i].init();
 53     }
 54     dis[S]=0,flag[S]=1;
 55     queue<int>q;q.push(S);
 56     while(!q.empty())
 57     {
 58         int u=q.front();
 59         q.pop();
 60         for (int i=hed[u];i!=-1;i=nxt[i])
 61         {
 62             int v=rea[i],fee=cost[i];
 63             if ((dis[u]+fee<dis[v])&&val[i]>0)
 64             {
 65                 dis[v]=dis[u]+fee;
 66                 pre[v].fa=u,pre[v].e=i;
 67                 if (flag[v]==0)
 68                 {
 69                     flag[v]==1;
 70                     q.push(v);
 71                 }
 72             }
 73         }
 74         flag[u]=0;
 75     }
 76     if (dis[T]!=inf) return 1;
 77     else return 0;
 78 }
 79 void MFMC()
 80 {
 81     int Flow=0,Cost=0;
 82     while (Spfa())
 83     {
 84         int x=inf;
 85         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
 86         {
 87             int e=pre[i].e;
 88             x=min(x,val[e]);
 89         }
 90         Flow+=x,Cost+=x*dis[T];
 91         for (int i=T;pre[i].fa!=-1;i=pre[i].fa)
 92         {
 93             int e=pre[i].e;
 94             val[e]-=x,val[e^1]+=x;
 95         }
 96     }
 97     printf("%d\n",Cost);
 98 }
 99 int main()
100 {
101     memset(hed,-1,sizeof(hed));
102     n=read(),m=read(),k=read();
103     for (int i=0;i<=n;i++)
104         for (int j=0;j<=n;j++)
105             a[i][j]=inf;
106     for (int i=1;i<=m;i++)
107     {
108         int u=read(),v=read(),fee=read();
109         a[u][v]=min(a[u][v],fee);
110         a[v][u]=min(a[v][u],fee);
111     }
112     Floyd();
113     S=2*(n+1),T=S+1;
114     for (int i=0;i<n;i++)
115         for (int j=i+1;j<=n;j++)
116             if (a[i][j]!=inf) add(i,j+n+1,1,a[i][j]),add(j+n+1,i,0,-a[i][j]);
117     for (int i=1;i<=n;i++)
118         add(S,i,1,0),add(i,S,0,0);
119     add(S,0,k,0),add(0,S,0,0);
120     for (int i=1;i<=n;i++)
121         add(i+n+1,T,1,0),add(T,i+n+1,0,0);
122     MFMC();
123 }

 

posted @ 2017-12-29 09:32  Kaiser-  阅读(184)  评论(0编辑  收藏  举报