[BZOJ2407/4398]-探险/福慧双修-最短路+建图
2018-03-05 09:27
405 查看
说在前面
me没有去参加开学典礼会不会被老师打啊…题目
这双倍经验题两个题号都是权限题…emmmmBZOJ2407传送门
BZOJ4398传送门
2407的题面
探险家小T好高兴!X国要举办一次溶洞探险比赛,获奖者将得到丰厚奖品哦!小T虽然对奖品不感兴趣,但是这个大振名声的机会当然不能错过!比赛即将开始,工作人员说明了这次比赛的规则:每个溶洞和其他某些溶洞有暗道相连。两个溶洞之间可能有多条道路,也有可能没有,但没有一条暗道直接从自己连到自己。参赛者需要统一从一个大溶洞出发,并再次回到这个大溶洞。
如果就这么点限制,那么问题就太简单了,可是举办方又提出了一个条件:不能经过同一条暗道两次。这个条件让大家犯难了。这该怎么办呢?
到了大溶洞口后,小T愉悦地发现这个地方他曾经来过,他还记得有哪些暗道,以及通过每条暗道的时间。小T现在向你求助,你能帮他算出至少要多少时间才能回到大溶洞吗?
输入输出格式
输入格式:第一行两个整数N,M,表示点数和边数
接下来M行,每行(u,v,fw,bw)描述一条边,表示该边连通u和v,顺着走时间fw,逆着走时间bw
输出格式:
输出一行一个整数,表示符合条件的最短路
解法
题目要求,最短路不能来回走。一个最简单粗暴且合法的方法就是,先确定走出去的第一条边,然后把回去的路割掉(因为去掉了这种路之后,如果绕路一定不优),之后再跑最短路,对1的每一条出边都这么做一次,显然可以得到最优解。然而这种做法肯定是要T的。重新思考一下这道题的限制,如果一个与1相邻的点u,它的最短路第一条出边并不是u,那么就可以用dis[u]+length更新答案(即存在1->v->….->u->1这样的路径),而如果u的最短路第一条出边就是u,那么就不能用dis[u]+length去更新答案(显然这时最短路为1->u->1)。但是如果存在另外的某一条路1->v->…->u的话,是可以用dis′[u]+length更新答案的。记1到u的最短路第一条出边为pre[u],那么合法的最短路一定是形如1->u->v->1且pre[u]!=pre[v]
那么建一张新图,新开节点T,对于原图的每一条单向边(u1,v,len)
如果u是1:如果pre[v] != v,建边(1,v,dis[v]),不然不建边
如果v是1:如果pre[u] != u,建边(1,T,dis[u]+length),不然建边(u,T,length)
如果uv都不是1:如果pre[u] != pre[v],建边(1,v,dis[u]+length),不然建边(u,v,length)
为什么这样建边呢?因为这样的话,新图中每一条从1出发的边,一定是绕过路的,而每一条与终点相连的边,一定都是没有绕过路的。于是新图中1到T的每一条路径,都一定在原图满足出发边和回边不一样(因为只要不是1->u->…->u->1,其余都是合法路径),那么对新图跑最短路,dis[T]就是最终答案
感觉这个题还是挺妙的,但是这个建图方法…貌似比较个例
下面是代码
#include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; int N , M , tp , head[40005] , T ; struct Edge{ int u , v , fw , bw ;// forward && backward void read_(){ scanf( "%d%d%d%d" , &u , &v , &fw , &bw ) ; if( u > v ) swap( u , v ) , swap( fw , bw ) ; } }e[200005] ; struct Path{ int pre , to , len ; }p[400005] ; inline void In( int t1 , int t2 , int t3 ){ p[++tp] = ( Path ){ head[t1] , t2 , t3 } ; head[t1] = tp ; } int dis[40005] , pre[40005] ; struct Data{ int id , dis ; bool operator < ( const Data &A ) const { return dis > A.dis ; } } ; priority_queue<Data> que ; void Dijk( bool UPD ){ memset( dis , 0x3f , sizeof( dis ) ) ; dis[1] = 0 ; que.push( ( Data ){ 1 , 0 } ) ; while( !que.empty() ){ Data u = que.top() ; que.pop() ; if( u.dis > dis[u.id] ) continue ; for( int i = head[u.id] ; i ; i = p[i].pre ){ int v = p[i].to ; if( dis[v] > u.dis + p[i].len ){ if( UPD ) pre[v] = ( u.id == 1 ? v : pre[u.id] ) ; dis[v] = u.dis + p[i].len ; que.push( ( Data ){ v , dis[v] } ) ; } } } } /*bool inque[40005] ; int que[5000005] , fr , ba ; void Spfa(){ fr = 1 , ba = 0 ; memset( dis , 0x3f , sizeof( dis ) ) ; dis[1] = 0 ; que[++ba] = 1 , inque[1] = true ; while( fr <= ba ){ int u = que[fr++] ; inque[u] = false ; for( int i = head[u] ; i ; i = p[i].pre ){ int v = p[i].to ; if( dis[v] > dis[u] + p[i].len ){ pre[v] = ( u == 1 ? v : pre[u] ) ; dis[v] = dis[u] + p[i].len ; if( !inque[v] ){ que[++ba] = v ; inque[v] = true ; } } } } }*/ void solve(){ Dijk( 1 ) ; tp = 0 ; memset( head , 0 , sizeof( head ) ) ; for( int i = 1 ; i <= M ; i ++ ){ int u = e[i].u , v = e[i].v ; if( u == 1 ){ if( pre[v] != v ){ In( 1 , v , dis[v] ) ;// direction :1 to v In( 1 , T , dis[v] + e[i].bw ) ;// direction :v to 1 } else In( v , T , e[i].bw ) ;// direction :v to 1 } else { if( pre[v] == pre[u] ){ In( u , v , e[i].fw ) ;// direction :u to v In( v , u , e[i].bw ) ;// direction :v to u } else{ In( 1 , v , dis[u] + e[i].fw ) ;// direction :u to v In( 1 , u , dis[v] + e[i].bw ) ;// direction :v to u } } } Dijk( 0 ) ; printf( "%d" , dis[T] ) ; } int main(){ scanf( "%d%d" , &N , &M ) ; T = N + 1 ; for( int i = 1 ; i <= M ; i ++ ){ e[i].read_() ; In( e[i].u , e[i].v , e[i].fw ) ; In( e[i].v , e[i].u , e[i].bw ) ; } solve() ; }
相关文章推荐
- 【BZOJ2407/4398】探险/福慧双修 最短路建模
- BZOJ_4398_福慧双修&&BZOJ_2407_探险_分治+dij
- BZOJ 2407: 探险/BZOJ 4398: 福慧双修 dijkstra 构造
- bzoj 2407: 探险 最短路+构造
- bzoj 4398 福慧双修 - 最短路
- [BZOJ4398]福慧双修/[BZOJ2407]探险
- bzoj 4398 福慧双修 题解
- bzoj 2407 最短路
- BZOJ 2407 探险
- BZOJ - 2407 探险 Dijkstra + 重构图
- bzoj 1726: [Usaco2006 Nov]Roadblocks第二短路(A*第k短路)
- 【最小割->最短路】BZOJ1001(BeiJing2006)[狼抓兔子]题解
- bzoj 1598 K短路 A*
- [BZOJ 1266][AHOI2006]上学路线(最短路+最小割)
- BZOJ4144 [AMPPZ2014]Petrol 【最短路 + 最小生成树】
- [BZOJ2125][仙人掌]最短路
- BZOJ 3073: [Pa2011]Journeys 线段树优化最短路
- BZOJ 2015: [Usaco2010 Feb]Chocolate Giving( 最短路 )
- bzoj 1598: [Usaco2008 Mar]牛跑步 -- 第k短路,A*
- BZOJ 1003 物流运输trans(最短路)