【UVALive】3661 Animal Run 平面图最小割 最短路

2024-09-05 15:38

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



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

相关文章

poj 1511 Invitation Cards(spfa最短路)

题意是给你点与点之间的距离,求来回到点1的最短路中的边权和。 因为边很大,不能用原来的dijkstra什么的,所以用spfa来做。并且注意要用long long int 来存储。 稍微改了一下学长的模板。 stack stl 实现代码: #include<stdio.h>#include<stack>using namespace std;const int M

poj 3259 uva 558 Wormholes(bellman最短路负权回路判断)

poj 3259: 题意:John的农场里n块地,m条路连接两块地,w个虫洞,虫洞是一条单向路,不但会把你传送到目的地,而且时间会倒退Ts。 任务是求你会不会在从某块地出发后又回来,看到了离开之前的自己。 判断树中是否存在负权回路就ok了。 bellman代码: #include<stdio.h>const int MaxN = 501;//农场数const int

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

poj 1502 MPI Maelstrom(单源最短路dijkstra)

题目真是长得头疼,好多生词,给跪。 没啥好说的,英语大水逼。 借助字典尝试翻译了一下,水逼直译求不喷 Description: BIT他们的超级计算机最近交货了。(定语秀了一堆词汇那就省略吧再见) Valentine McKee的研究顾问Jack Swigert,要她来测试一下这个系统。 Valentine告诉Swigert:“因为阿波罗是一个分布式共享内存的机器,所以它的内存访问

poj 3159 (spfa差分约束最短路) poj 1201

poj 3159: 题意: 每次给出b比a多不多于c个糖果,求n最多比1多多少个糖果。 解析: 差分约束。 这个博客讲差分约束讲的比较好: http://www.cnblogs.com/void/archive/2011/08/26/2153928.html 套个spfa。 代码: #include <iostream>#include <cstdio>#i

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

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

hdu 3790 (单源最短路dijkstra)

题意: 每条边都有长度d 和花费p,给你起点s 终点t,要求输出起点到终点的最短距离及其花费,如果最短距离有多条路线,则输出花费最少的。 解析: 考察对dijkstra的理解。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstrin

hdu 1102 uva 10397(最小生成树prim)

hdu 1102: 题意: 给一个邻接矩阵,给一些村庄间已经修的路,问最小生成树。 解析: 把已经修的路的权值改为0,套个prim()。 注意prim 最外层循坏为n-1。 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstri