BZOJ 2324 营救皮卡丘
http://www.lydsy.com/JudgeOnline/problem.php?id=2324
思路:最小费用最大流
考虑设数组d[k][i][j],代表只用前k个城市,i到j的最短路
然后可以这样建图
S->0 流量为K,费用为0
i->i+n 流量为inf,费用为0
i+n->T 流量为1
i+n->j 流量为inf,费用为d[j][i][j]
S->i 流量为1,费用为0 代表如果一个人到了i城市,它可以继续走,从而续出来的一个新流量。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define inf 0x7fffffff 7 int d[205][205][205],a[205][205],K; 8 int tot,go[200005],next[200005],first[200005],cost[200005],flow[200005]; 9 int op[200005],dis[200005],c[200005],vis[200005],edge[200005],from[200005]; 10 int S,T,n,m,ans; 11 int read(){ 12 char ch=getchar();int t=0,f=1; 13 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 14 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 15 return t*f; 16 } 17 void insert(int x,int y,int z,int l){ 18 tot++; 19 go[tot]=y; 20 next[tot]=first[x]; 21 first[x]=tot; 22 flow[tot]=z; 23 cost[tot]=l; 24 } 25 void add(int x,int y,int z,int l){ 26 insert(x,y,z,l);op[tot]=tot+1; 27 insert(y,x,0,-l);op[tot]=tot-1; 28 } 29 bool spfa(){ 30 for (int i=0;i<=T;i++) 31 dis[i]=0x3f3f3f3f,vis[i]=0; 32 int h=1,t=1;c[1]=S;vis[S]=1;dis[S]=0; 33 while (h<=t){ 34 int now=c[h++]; 35 for (int i=first[now];i;i=next[i]){ 36 int pur=go[i]; 37 if (dis[pur]>dis[now]+cost[i]&&flow[i]){ 38 dis[pur]=dis[now]+cost[i]; 39 edge[pur]=i; 40 from[pur]=now; 41 if (vis[pur]) continue; 42 vis[pur]=1; 43 c[++t]=pur; 44 } 45 } 46 vis[now]=0; 47 } 48 return dis[T]!=0x3f3f3f3f; 49 } 50 void updata(){ 51 int mn=0x7ffffff; 52 for (int i=T;i!=S;i=from[i]){ 53 mn=std::min(mn,flow[edge[i]]); 54 } 55 for (int i=T;i!=S;i=from[i]){ 56 ans+=mn*cost[edge[i]]; 57 flow[edge[i]]-=mn; 58 flow[op[edge[i]]]+=mn; 59 } 60 } 61 int main(){ 62 n=read();m=read();K=read(); 63 for (int i=0;i<=n;i++) 64 for (int j=0;j<=n;j++) 65 if (i!=j){ 66 a[i][j]=0x3f3f3f3f; 67 }else 68 a[i][j]=0; 69 for (int i=1;i<=m;i++){ 70 int u=read(),v=read(),w=read(); 71 a[u][v]=std::min(a[u][v],w); 72 a[v][u]=std::min(a[v][u],w); 73 } 74 for (int k=0;k<=n;k++){ 75 for (int i=0;i<=n;i++) 76 for (int j=0;j<=n;j++) 77 a[i][j]=std::min(a[i][k]+a[k][j],a[i][j]); 78 for (int i=0;i<=n;i++) 79 for (int j=0;j<=n;j++) 80 d[k][i][j]=a[i][j]; 81 } 82 S=2*n+2;T=S+1; 83 add(S,0,K,0); 84 for (int i=0;i<=n;i++) 85 add(i,i+n+1,inf,0); 86 for (int i=0;i<=n;i++) 87 add(i,T,1,0); 88 for (int i=0;i<=n;i++) 89 add(S,i+n+1,1,0); 90 for (int i=0;i<=n;i++) 91 for (int j=i+1;j<=n;j++) 92 if (d[j][i][j]<0x3f3f3f3f) 93 add(i+n+1,j,inf,d[j][i][j]); 94 while (spfa()) updata(); 95 printf("%d\n",ans); 96 }