您的位置:首页 > 其它

hdu 4411 Arrest【最小费用流】

2016-08-24 15:36 405 查看
题目链接

题意:

给定一个有(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]
<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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: