本文主要是介绍hdu 4411 Arrest【最小费用流】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目链接
题意:
给定一个有(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 1005
typedef 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;
}
这篇关于hdu 4411 Arrest【最小费用流】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!