hdu 4411 Arrest【最小费用流】

来源:互联网 发布:淘宝网宠物店能信吗 编辑:程序博客网 时间:2024/05/29 10:57

题目链接

题意:

给定一个有(n+1)个节点的边权图,其中警察局在0点,其他n个点各有一个黑手党,现在警察局派出k个警察去抓黑手党,并逮捕会警察局,一旦黑手党i被抓,他会向黑手党i-1报信,任务就会失败,求使任务成功的的最小花费?

思路:

要使黑手党之间不能通讯,必须以1到n的顺序来抓捕,那么每个警察的抓捕顺序只能从小到大。警察从一个城市到另一个城市一定走的是两个城市间的最短路。
首先可以floyd求dis[i][j];
建图如下:
(1)n个城市拆成入点和出点,之间建边,容量为1,花费为-1000000(一个足够小的数,保证这条边一定被通过)
(2)源点s到0,容量为k,花费为0
(3)0到汇点t,容量为k,花费为0;0到第i个城市的入点,容量为1,花费为dis[0][i]
(4)对所有i<j,建容量为1,花费为dis[i][j]的边
(5)第i个城市的出点到汇点t,容量为1,花费为dis[0][i]
固定流量为k,用最小费用流跑一遍,答案加上n*1000000。

代码:

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<algorithm>#include<map>#include<string>#include<queue>#include<vector>#include<list>#include<bitset>//#pragma comment(linker,"/STACK:1024000000,1024000000")using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define MAX_V 1005typedef pair<int,int> P;struct edge{    int to,cap,cost,rev;};int V;vector<edge> G[MAX_V];int h[MAX_V];int dist[MAX_V];int prevv[MAX_V],preve[MAX_V];void add_edge(int from,int to,int cap,int cost){    G[from].push_back((edge)    {        to,cap,cost,G[to].size()    });    G[to].push_back((edge)    {        from,0,-cost,G[from].size()-1    });}int min_cost_flow(int s,int t,int f){    int res=0;    fill(h,h+V,0);    while(f>0)    {        priority_queue<P, vector<P> ,greater<P> >que;        fill(dist,dist+V,INF);        dist[s]=0;        que.push(P(0,s));        while(!que.empty())        {            P p=que.top();            que.pop();            int v=p.second;            if(dist[v]<p.first) continue;            for(int i=0; i<G[v].size(); i++)            {                edge &e=G[v][i];                if(e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to])                {                    dist[e.to]=dist[v]+e.cost+h[v]-h[e.to];                    prevv[e.to]=v;                    preve[e.to]=i;                    que.push(P(dist[e.to],e.to));                }            }        }        if(dist[t]==INF)        {            return -1;        }        for(int v=0; v<V; v++) h[v]+=dist[v];        int d=f;        for(int v=t; v!=s; v=prevv[v])        {            d=min(d,G[prevv[v]][preve[v]].cap);        }        f-=d;        res+=d*h[t];        for(int v=t;v!=s;v=prevv[v])        {            edge &e=G[prevv[v]][preve[v]];            e.cap-=d;            G[v][e.rev].cap+=d;        }    }    return res;}int n,m,K;int dis[205][205];int main(){    while(~scanf("%d%d%d",&n,&m,&K)&&n+m+K)    {        V=2*n+5;        int s=V-2,t=V-1;        for(int i=0;i<MAX_V;i++) G[i].clear();        memset(dis,0x3f,sizeof dis);        for(int i=1;i<=m    ;i++)        {            int u,v,w;            scanf("%d%d%d",&u,&v,&w);            dis[u][v]=dis[v][u]=min(dis[u][v],w);        }        for(int k=0;k<=n;k++)            for(int i=0;i<=n;i++)            for(int j=0;j<=n;j++)        {            dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);        }        add_edge(s,0,K,0);        add_edge(0,t,K,0);        for(int i=1;i<=n;i++)        {            add_edge(0,i,1,dis[0][i]);            add_edge(i,n+i,1,-1000000);            add_edge(n+i,t,1,dis[0][i]);        }        for(int i=1;i<=n;i++)        {            for(int j=i+1;j<=n;j++)            {                if(dis[i][n]<INF) add_edge(i+n,j,1,dis[i][j]);            }        }        int ans=min_cost_flow(s,t,K);        ans+=n*1000000;        printf("%d\n",ans);    }    return 0;}


1 0
原创粉丝点击