【HDU】4411 Arrest 费用流

news/2024/11/26 4:46:07/

传送门:【HDU】4411 Arrest


题目分析:题目的意思一开始没看懂= =。。。题意大致为:派出至多K个警队遵守先灭小的再灭老的的原则将N个城市的帮派全端了(要灭编号大的必须要先灭编号小的)。且一个警队可以一次端多个城市。

首先floyd预处理出所有点对之间的最短路,题目保证两点之间一定可达。令G[i][j]为i到j的最短路。

题目要求的必须先灭i才能灭i+1总可以通过合理的警队剿灭顺序做到(比如警队1灭了帮派1,警队2灭了帮派2然后回家,然后警队1再灭了帮派3再回家)。于是本题转化成K路径覆盖问题。首先每个点都必须被走到,那么将一个点 i 拆成两个点i、i+n,然后建边( i , i + n , 1 , -M ),其中M为比最大的路径长度还大的一个数,目的是为了一定将点i取到,这里设为100000(100000>99*1000)。容量为1表示只能被剿灭一次。

然后设立源点s,汇点t,源点向0建边( s , 0 , K , 0 )表示至多能派K个警队。0向1~n建边( 0 , i , 1 , G[ 0 ][ i ] )表示一支警队从0出发到i(为什么容量设为1?因为只用一支警队去剿灭帮派i,而且如果有别的警队要去剿灭别的帮派必须要经过i的话,那么最短路上其实已经算上0~i的最短路了,所以没必要重复添加,并且正好和上面的建图对应)。

1~n向汇点建边( i + n , t , 1 , G[ i ][ 0 ] )表示警队抓完帮派i回家(0)了。

然后对所有的点i,向所有的j( j > i )建边( i + n , j , 1 , G[ i ][ j ] )表示抓完帮派i要去抓帮派j了(因为只能抓了小的才能抓大的,所以只能是小的向大的建边)。

最后,由于当费用最小的时候并不是最大流(不是所有的警察都一定要用到),所以建边( 0 , t , K , 0 )表示用不到的警察直接不出门了。


代码如下:


#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;#define REP( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; -- i )
#define travel( e , H , u ) for ( Edge* e = H[u] ; e ; e = e -> next )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define cPY( a , x ) memcpy ( a , x , sizeof a )const int M = 100000 ;
const int MAXN = 205 ;
const int MAXE = 20000 ;
const int INF = 0x3f3f3f3f ;struct Edge {int v , c , w , n ;Edge () {}Edge ( int v , int c , int w , int n ) : v ( v ) , c ( c ) , w ( w ) , n ( n ) {}
} ;struct Net {Edge E[MAXE] ;int H[MAXN] , cntE ;int d[MAXN] , cap[MAXN] , cur[MAXN] ;int Q[MAXN] , head , tail ;bool vis[MAXN] ;int s , t ;int flow , cost ;int n , m , K ;int G[105][105] ;void init () {cntE = 0 ;CLR ( H , -1 ) ;}void addedge ( int u , int v , int c , int w ) {E[cntE] = Edge ( v , c ,  w , H[u] ) ;H[u] = cntE ++ ;E[cntE] = Edge ( u , 0 , -w , H[v] ) ;H[v] = cntE ++ ;}bool spfa () {CLR ( d , INF ) ;CLR ( vis , 0 ) ;head = tail = 0 ;cap[s] = INF ;cur[s] = -1 ;d[s] = 0 ;Q[tail ++] = s ;while ( head != tail ) {int u = Q[head ++] ;if ( head == MAXN ) head = 0 ;vis[u] = 0 ;for ( int i = H[u] ; ~i ; i = E[i].n ) {int v = E[i].v , c = E[i].c , w = E[i].w ;if ( c && d[v] > d[u] + w ) {d[v] = d[u] + w ;cap[v] = min ( c , cap[u] ) ;cur[v] = i ;if ( !vis[v] ) {vis[v] = 1 ;if ( d[v] < d[Q[head]] ) {if ( head == 0 ) head = MAXN ;Q[-- head] = v ;} else {Q[tail ++] = v ;if ( tail == MAXN ) tail = 0 ;}}}}}if ( d[t] == INF ) return 0 ;flow += cap[t] ;cost += cap[t] * d[t] ;for ( int i = cur[t] ; ~i ; i = cur[E[i ^ 1].v] ) {E[i].c -= cap[t] ;E[i ^ 1].c += cap[t] ;}return 1 ;}int MCMF () {flow = cost = 0 ;while ( spfa () ) ;return cost ;}void solve () {int u , v , c , w ;init () ;CLR ( G , INF ) ;s = n << 1 | 1 ;t = s + 1 ;while ( m -- ) {scanf ( "%d%d%d" , &u , &v , &w ) ;G[u][v] = G[v][u] = min ( G[u][v] , w ) ;}FOR ( k , 0 , n ) FOR ( i , 0 , n ) FOR ( j , 0 , n ) G[i][j] = min ( G[i][j] , G[i][k] + G[k][j] ) ;FOR ( i , 1 , n ) addedge ( i , i + n , 1 , -M ) ;FOR ( i , 1 , n ) addedge ( 0 , i , 1 , G[0][i] ) ;FOR ( i , 1 , n ) addedge ( i + n , t , 1 , G[i][0] ) ;FOR ( i , 1 , n ) FOR ( j , i + 1 , n ) addedge ( i + n , j , 1 , G[i][j] ) ;addedge ( s , 0 , K , 0 ) ;addedge ( 0 , t , K , 0 ) ;printf ( "%d\n" , MCMF () + M * n ) ;}
} e ;int main () {while ( ~scanf ( "%d%d%d" , &e.n , &e.m , &e.K ) && ( e.n || e.m || e.K ) ) e.solve () ;return 0 ;
}



http://www.ppmy.cn/news/370608.html

相关文章

HDU 4411最小费用流

点击打开链接 题意&#xff1a;从0出发&#xff0c;1~N每个城镇有个小偷&#xff0c;我们要把他们全部抓到&#xff0c;我们可以派出k个警察&#xff0c;但是再抓i城镇的小偷之前&#xff0c;i城镇之前的所有城镇的小偷已经被抓了 思路&#xff1a;哪有什么思路,看了网上的题…

hdu4411(费用流)

链接&#xff1a;点击打开链接 题意&#xff1a;给n1个点&#xff0c;m条边的无向图。起点为0&#xff0c;k个人初始在起点&#xff0c;去遍历图使得每个点至少被一人走过并且遍历i点时i-1必须已经被遍历&#xff0c;最后k人要回到起点。输出k个人最小的路径和 代码&#xff…

hdu4411 Arrest(费用流)

题目链接&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid4411 【题意】给定N1个点&#xff0c;距离&#xff0c;K个人&#xff0c;问&#xff0c;每人从0开始按照升序访问节点然后回到0&#xff0c;每个节点被访问一次的最小距离和。 【分析】费用流问题&#xff0c;因…

P4411BZOJ1978 [BJWC2010]取数游戏(动态规划dp)

P4411 一道dp f[i]表示一定选第i个数的条件下前i个数所能得到的最优值 last[i]表示质因数i在数列a中最后出现时的下标 状态转移方程为\(f[i]max\{f[last[j]\:|\: j|i \}1\) 复杂度\(O(n\sqrt{a_i})\) #include <bits/stdc.h> using namespace std; int n,l,ans,a[50005],…

ubuntu4411

http://bothlog.com/index.php/2010/08/resolve-ubuntu-10-04-ait-card-can-not-adjust-brightness-by-fn-key/

bzoj4411 [Usaco2016 Feb]Load balancing

http://www.elijahqi.win/archives/3059 Description 给出N个平面上的点。保证每一个点的坐标都是正奇数。 你要在平面上画两条线&#xff0c;一条是xa&#xff0c;一条是yb&#xff0c;且a和b都是偶数。 直线将平面划成4个部分&#xff0c;要求包含点数最多的那个部分点数…

HDU 4411 Arrest

分析&#xff1a;很明显的费用流&#xff0c;最重要的还是建图&#xff0c;首先确立源点和汇点&#xff0c;因为城市0为初始点&#xff0c;所以我定义s为源点&#xff0c;然后t为汇点&#xff0c;s-->0建边&#xff0c;流量为k&#xff0c;费用为0&#xff0c;因为不一定所有…

惠普电脑为什么打不开计算机刷题,如果无法打开HP笔记本计算机的无线开关该怎么办?惠普ProBook 4411s...

clp615808 通过 尊敬的HP用户&#xff0c;您好&#xff01;感谢您选择惠普产品. 根据您的描述&#xff0c;建议您参考以下信息: 1. 建议进入操作系统的桌面. 您可以右键单击[计算机](或[我的计算机])图标&#xff0c;选择[管理]&#xff0c;然后在页面左侧的[设备管理器]中-右键…