hdu 4411 Arrest【最小费用流】

2024-02-13 15:38
文章标签 最小 费用 hdu 4411 arrest

本文主要是介绍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【最小费用流】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/705925

相关文章

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

hdu 2093 考试排名(sscanf)

模拟题。 直接从教程里拉解析。 因为表格里的数据格式不统一。有时候有"()",有时候又没有。而它也不会给我们提示。 这种情况下,就只能它它们统一看作字符串来处理了。现在就请出我们的主角sscanf()! sscanf 语法: #include int sscanf( const char *buffer, const char *format, ... ); 函数sscanf()和

hdu 2602 and poj 3624(01背包)

01背包的模板题。 hdu2602代码: #include<stdio.h>#include<string.h>const int MaxN = 1001;int max(int a, int b){return a > b ? a : b;}int w[MaxN];int v[MaxN];int dp[MaxN];int main(){int T;int N, V;s

poj 1258 Agri-Net(最小生成树模板代码)

感觉用这题来当模板更适合。 题意就是给你邻接矩阵求最小生成树啦。~ prim代码:效率很高。172k...0ms。 #include<stdio.h>#include<algorithm>using namespace std;const int MaxN = 101;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int n

poj 1287 Networking(prim or kruscal最小生成树)

题意给你点与点间距离,求最小生成树。 注意点是,两点之间可能有不同的路,输入的时候选择最小的,和之前有道最短路WA的题目类似。 prim代码: #include<stdio.h>const int MaxN = 51;const int INF = 0x3f3f3f3f;int g[MaxN][MaxN];int P;int prim(){bool vis[MaxN];

poj 2349 Arctic Network uva 10369(prim or kruscal最小生成树)

题目很麻烦,因为不熟悉最小生成树的算法调试了好久。 感觉网上的题目解释都没说得很清楚,不适合新手。自己写一个。 题意:给你点的坐标,然后两点间可以有两种方式来通信:第一种是卫星通信,第二种是无线电通信。 卫星通信:任何两个有卫星频道的点间都可以直接建立连接,与点间的距离无关; 无线电通信:两个点之间的距离不能超过D,无线电收发器的功率越大,D越大,越昂贵。 计算无线电收发器D

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

poj 1734 (floyd求最小环并打印路径)

题意: 求图中的一个最小环,并打印路径。 解析: ans 保存最小环长度。 一直wa,最后终于找到原因,inf开太大爆掉了。。。 虽然0x3f3f3f3f用memset好用,但是还是有局限性。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#incl