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);

    }
}
View Code

 

posted @ 2013-09-10 20:15  等待最好的两个人  阅读(134)  评论(0编辑  收藏  举报