本文主要是介绍【UVALive】3661 Animal Run 平面图最小割 最短路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
传送门:【UVALive】3661 Animal Run
题目大意:给你一个n*m个点的网格图,其中动物园在左上角,动物们的目的地在右下角,现在你需要派出一些工作人员拦截某些边使得没有一只动物能到达右下角,已知每个单元网格中存在左上角到右下角的对角线,网格中的边以及对角线都是双向的,每条道路有个权值,表示拦截这条边所需要的工作人员数。你的任务是派尽量少的工作人员使得达到目的。
题目分析:本题和【HDU】3870 Catch the Theves 几乎一样(【HDU】3870 题解戳这里),就是需要多设一倍的点,没什么太大变化,照着无向图最小割,对偶图转最短路做就行了~
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;#define up( i ) ( ( i ) << 1 )
#define down( i ) ( ( i ) << 1 | 1 )
#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )
#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )
#define REPV( i , a , b ) for ( int i = a ; i >= b ; -- i )
#define clear( a , x ) memset ( a , x , sizeof a )const int MAXN = 2000000 ;
const int MAXE = 7000000 ;
const int MAXH = 7000000 ;
const int INF = 0x7f7f7f7f ;struct Edge {int v , c , n ;Edge ( int var = 0 , int cost = 0 , int next = 0 ) :v ( var ) , c ( cost ) , n ( next ) {}
} ;struct Heap {int w , idx ;Heap ( int _w = 0 , int _idx = 0 ) :w ( _w ) , idx ( _idx ) {}
} ;struct priority_queue {Heap heap[MAXH] ;int top ;void init () {top = 1 ;}int cmp ( const Heap &a , const Heap &b ) {return a.w < b.w ;}void push ( int w , int idx ) {heap[top] = Heap ( w , idx ) ;int o = top ++ ;while ( o > 1 && cmp ( heap[o] , heap[o >> 1] ) )swap ( heap[o] , heap[o >> 1] ) , o >>= 1 ;}int front () {return heap[1].idx ;}int empty () {return top == 1 ;}void pop () {heap[1] = heap[-- top] ;int o = 1 , p = o , l = o << 1 , r = o << 1 | 1 ;while ( o < top ) {if ( l < top && cmp ( heap[l] , heap[p] ) )p = l ;if ( r < top && cmp ( heap[r] , heap[p] ) )p = r ;if ( p == o )break ;swap ( heap[o] , heap[p] ) ;o = p , l = o << 1 , r = o << 1 | 1 ;}}
} ;struct Dij {priority_queue q ;Edge edge[MAXE] ;int adj[MAXN] , cntE ;int d[MAXN] ;int done[MAXN] ;void init () {cntE = 0 ;clear ( adj , -1 ) ;}void addedge ( int u , int v , int c ) {edge[cntE] = Edge ( v , c , adj[u] ) ;adj[u] = cntE ++ ;edge[cntE] = Edge ( u , c , adj[v] ) ;adj[v] = cntE ++ ;}void dijkstra ( int s , int t ) {q.init () ;clear ( d , INF ) ;clear ( done , 0 ) ;d[s] = 0 ;q.push ( d[s] , s ) ;while ( !q.empty () ) {int u = q.front () ;q.pop () ;if ( done[u] )continue ;done[u] = 1 ;for ( int i = adj[u] ; ~i ; i = edge[i].n ) {int v = edge[i].v , c = edge[i].c ;if ( d[v] > d[u] + c ) {d[v] = d[u] + c ;q.push ( d[v] , v ) ;}}}}
} ;Dij z ;void work () {int n , m ;int s , t ;int x , mm ;int cas = 0 ;while ( ~scanf ( "%d%d" , &n , &m ) && ( n || m ) ) {printf ( "Case %d: Minimum = " , ++ cas ) ;z.init () ;mm = m - 1 ;s = ( n - 1 ) * mm * 2 ;t = s + 1 ;REP ( i , n )REP ( j , m - 1 ) {scanf ( "%d" , &x ) ;if ( i == 0 )z.addedge ( up ( i ) * mm + j , t , x ) ;else if ( i < n - 1 )z.addedge ( up ( i ) * mm + j , down ( i - 1 ) * mm + j , x ) ;else if ( i == n - 1 )z.addedge ( s , down ( i - 1 ) * mm + j , x ) ;}REP ( i , n - 1 )REP ( j , m ) {scanf ( "%d" , &x ) ;if ( j == 0 )z.addedge ( s , down ( i ) * mm + j , x ) ;else if ( j < m - 1 )z.addedge ( up ( i ) * mm + j - 1 , down ( i ) * mm + j , x ) ;else if ( j == m - 1 )z.addedge ( up ( i ) * mm + j - 1 , t , x ) ;}REP ( i , n - 1 )REP ( j , m - 1 ) {scanf ( "%d" , &x ) ;z.addedge ( down ( i ) * mm + j , up ( i ) * mm + j , x ) ;}z.dijkstra ( s , t ) ;printf ( "%d\n" , z.d[t] ) ;}
}int main () {work () ;return 0 ;
}
这篇关于【UVALive】3661 Animal Run 平面图最小割 最短路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!