hdu 4411 arrest 最小费用流
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <algorithm> #include <queue> #include <vector> using namespace std; const int maxe = 100000; const int maxn = 305; const int INF = 0x3f3f3f3f; int dist[maxn][maxn]; int N,M,K; const int Max = 1000000; struct Edge{ int u,v,flow,cap,cost; int next; Edge(int u=0,int v=0,int flow=0,int cap=0,int cost=0,int next=0): u(u), v(v), flow(flow), cap(cap), cost(cost), next(next){} }; struct MCMF{ Edge edges[maxe]; int head[maxn],cnt; int d[maxn]; bool inq[maxn]; int pa[maxn]; int res[maxn]; void init(){ memset(head,-1,sizeof(head)); cnt = 0; } void addedge(int u,int v,int cap,int cost){ edges[cnt] = Edge(u,v,0,cap,cost,head[u]); head[u] = cnt++; edges[cnt] = Edge(v,u,0,0,-cost,head[v]); head[v] = cnt++; } bool SPFA(int s,int t,int& flow,int& cost){ memset(d,0x3f,sizeof(d)); memset(inq,0,sizeof(inq)); queue<int> Q; Q.push(s); inq[s] = true; d[s] = 0; res[s] = INF; res[t] = 0; while(!Q.empty()){ int u = Q.front(); Q.pop(); inq[u] = false; for(int i=head[u];i!=-1;i=edges[i].next){ Edge& e = edges[i]; if(e.cap>e.flow && d[e.v] > d[u] + e.cost){ d[e.v] = d[u] + e.cost; pa[e.v] = i; res[e.v] = min(res[u],e.cap-e.flow); if(!inq[e.v]){ Q.push(e.v); inq[e.v] = true; } } } } if(res[t] == 0) return false; flow += res[t]; cost += res[t]*d[t]; for(int i=t;i!=s;i=edges[pa[i]].u){ edges[pa[i]].flow += res[t]; edges[pa[i]^1].flow -= res[t]; } return true; } int MinCost(int s,int t){ int flow = 0,cost = 0; while(SPFA(s,t,flow,cost)){} return cost; } }solver; void floyd(){ for(int k=0;k<=N;k++) for(int i=0;i<=N;i++){ if(dist[i][k] >= INF) continue; for(int j=0;j<=N;j++){ if(dist[k][j] >= INF) continue; dist[i][j] = min(dist[i][j],dist[i][k]+dist[k][j]); } } } int main() { //freopen("E:\\acm\\input.txt","r",stdin); while(scanf("%d %d %d",&N,&M,&K)==3 && N+M+K){ memset(dist,0x3f,sizeof(dist)); for(int i=0;i<=N;i++) dist[i][i] = 0; for(int i=1;i<=M;i++){ int u,v,w; scanf("%d %d %d",&u,&v,&w); if(dist[u][v] > w) dist[u][v] = dist[v][u] = w; } floyd(); solver.init(); int s = 2*N+2, t = 2*N+1; solver.addedge(s,0,K,0); solver.addedge(0,t,K,0); //有些警察可以一直待 在警局,不出来 for(int i=1;i<=N;i++){ solver.addedge(i,i+N,1,-Max); solver.addedge(0,i,1,dist[0][i]); solver.addedge(i+N,t,1,dist[i][0]); } //达到最大流的基础必须是所有的点的流都要被访问到。 for(int i=1;i<N;i++) for(int j=i+1;j<=N;j++){ solver.addedge(i+N,j,1,dist[i][j]); } printf("%d\n",solver.MinCost(s,t)+Max*N); } }