【Codeforces】449B Jzzhu and Cities 最短路

2024-09-05 15:38

本文主要是介绍【Codeforces】449B Jzzhu and Cities 最短路,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:【Codeforces】449B Jzzhu and Cities


题目大意:一个n个节点的无向图,节点编号1~n(其中1为起点),其中有m条普通普通,还有k条从起点出发的特殊边,问最多去掉多少的特殊边使得从起点到其他所有点的最短路径的距离不变。


题目分析:这题的意图很明显啊,就是要我们去求最短路啊。那么怎么求会比较好呢?其实我们可以很容易的发现如果从起点通过边权为c的特殊边到达顶点x,如果起点到x的最短路长度l < c,那么说明这条特殊边是可以去掉的。

什么,去掉会影响别的顶点的最短路?一定不会的啦,以为所有最短路径包括x的都可以用长度为l的路径来代替起点到x而不是比l长的这条特殊边。当然这是假设从起点到x没有特殊边,我们才可以用l代替c,那么如果起点到x的路径中包括了特殊边怎么办?

那么就变成一个子问题了:从起点到x的路径上y的最短路径判断的问题了。那么有没有可能绕了一圈又回到x?显然不可能,因为这样只可能最短路上的其他边的边权均为0(但是这个已经被题目限制了),而且这样l = c与一开始的条件矛盾。

好了,现在我们已经知道如果特殊边比最短路长那么就可以不选,如果l = c呢?我们该不该选呢?现在,假如我们记下了从起点到其他所有顶点的最短路的条数,当1->x的最短路条数只有1条的时候,那么那条最短路一定就是这条特殊边了,如果条数大于1,说明可以通过别的途径到达x,那么能不选特殊边就不选,何乐而不为呢?

很明显l>c是不可能出现的。怎么会出现最短路长度比一条能够直接到达x的边还长,你说是吧。

现在我们来分析一下特殊情况:如果同时有两条边权相同的特殊边连接x,并且除去他们最短路会变长,那么按照上面的方法判定,很明显,两条都会被删除!

那么我们该怎么避免?做法很简单,只要一开始预处理一下,对与一个顶点我们只保留一条特殊边就够了~


好了。。。唠叨了好多啊。。。。总体思路就是这样,2A,为什么是2A呢?因为最短路条数计数的时候会出现一个问题:可能条数过多就爆int了(爆long long 也是轻而易举),所以最后我特殊判断了一下,如果条数大于2,那么直接等于2就好了。。然后就过了。。。


代码如下:


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;#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 )typedef long long LL ;const int MAXN = 100005 ;
const int MAXE = 800005 ;
const int MAXH = 800005 ;
const int oo = 0x3f3f3f3f ;
const LL INF = 1e15 ;struct Edge {int v , n ;int c ;Edge () {}Edge ( int var , int cost , int next ) :v ( var ) , c ( cost ) , n ( next ) {}
} ;struct Node {int idx ;LL c ;Node () {}Node ( LL cost , int _idx ) :c ( cost ) , idx ( _idx ) {}bool operator < ( const Node &a ) const {return c < a.c ;}
} ;struct priority_queue {Node heap[MAXH] ;int point ;void init () {point = 1 ;}void push ( LL c , int idx ) {heap[point] = Node ( c , idx ) ;int o = point ++ ;while ( o > 1 && heap[o] < heap[o >> 1] )swap ( heap[o] , heap[o >> 1] ) , o >>= 1 ;}int empty () {return point == 1 ;}Node top () {return heap[1] ;}int front () {return heap[1].idx ;}void pop () {heap[1] = heap[-- point] ;int o = 1 , p = o , l = o << 1 , r = o << 1 | 1 ;while ( o < point ) {if ( l < point && heap[l] < heap[p] )p = l ;if ( r < point && 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 ;LL d[MAXN] ;bool done[MAXN] ;int cnt[MAXN] ;int dir[MAXN] ;int NV , NE , K ;int tot ;void init () {cntE = 0 ;clear ( dir , oo ) ;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 () {q.init () ;REP ( i , NV + 1 )d[i] = INF ;clear ( done , 0 ) ;clear ( cnt , 0 ) ;d[1] = 0 ;cnt[1] = 1 ;q.push ( d[1] , 1 ) ;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 ;cnt[v] = cnt[u] ;q.push ( d[v] , v ) ;}else if ( d[v] == d[u] + c ) {cnt[v] += cnt[u] ;if ( cnt[v] > 1 )cnt[v] = 2 ;}}}}void read ( int &x ) {x = 0 ;char c = ' ' ;while ( c < '0' || c > '9' )c = getchar () ;while ( c >= '0' && c <= '9' )x = x * 10 + c - '0' , c = getchar () ;}void input () {int u , v , c ;tot = 0 ;REP ( i , NE ) {read ( u ) , read ( v ) , read ( c ) ;addedge ( u , v , c ) ;}REP ( i , K ) {read ( v ) , read ( c ) ;if ( dir[v] > c )dir[v] = c ;}REPF ( i , 2 , NV )if ( dir[i] != oo ) {addedge ( 1 , i , dir[i] ) ;++ tot ;}}void solve () {init () ;input () ;dijkstra () ;REPF ( i , 2 , NV )if ( dir[i] != oo )if ( dir[i] > d[i] || dir[i] == d[i] && cnt[i] > 1 )-- tot ;printf ( "%d\n" , K - tot ) ;}
} ;Dij z ;int main () {while ( ~scanf ( "%d%d%d" , &z.NV , &z.NE , &z.K ) )z.solve () ;return 0 ;
}


这篇关于【Codeforces】449B Jzzhu and Cities 最短路的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

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 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

hdu 3790 (单源最短路dijkstra)

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

poj 3255 次短路(第k短路) A* + spfa 或 dijkstra

题意: 给一张无向图,求从1到n的次短路。 解析: A* + spfa 或者 dijkstra。 详解见上一题:http://blog.csdn.net/u013508213/article/details/46400189 本题,spfa中,stack超时,queue的效率最高,priority_queue次之。 代码: #include <iostream>#i

poj 2449 第k短路 A* + spfa

poj 2449: 题意: 给一张有向图,求第k短路。 解析: A* + spfa。 一下转自:http://blog.csdn.net/mbxc816/article/details/7197228 “描述一下怎样用启发式搜索来解决K短路。 首先我们知道A*的基础公式:f(x)=g(x)+h(x);对h(x)进行设计,根据定义h(x)为当前的x点到目标点t所需要的实际距

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

Codeforces Round #261 (Div. 2)小记

A  XX注意最后输出满足条件,我也不知道为什么写的这么长。 #define X first#define Y secondvector<pair<int , int> > a ;int can(pair<int , int> c){return -1000 <= c.X && c.X <= 1000&& -1000 <= c.Y && c.Y <= 1000 ;}int m

Codeforces Beta Round #47 C凸包 (最终写法)

题意慢慢看。 typedef long long LL ;int cmp(double x){if(fabs(x) < 1e-8) return 0 ;return x > 0 ? 1 : -1 ;}struct point{double x , y ;point(){}point(double _x , double _y):x(_x) , y(_y){}point op