【题目描述】
【分析】
题意:n个点,m条带权边的无向图,其中有k条特殊边连接1和i 问最多能删除多少条特殊边,能使每个点到1的最短距离不变 解答:直接在原图上跑最短路,得到dis[x]表示x到1的最短路。 对于每个用特殊边k连接的点i,如果dis[x]<w[k],那么k可以被删除 如果dis[x]=w[k],看x的其他出边如果也在最短路上,那么k也可以被删除 如此看来,原题就是一个裸的最短路
【代码】
#include <bits/stdc++.h>
using namespace std;
typedef pair< int , int > TQX;
const int N= 1e6 + 10 ;
int n, m, k, first[ N] , cnt, val[ N] , ans, vis[ N] , dis[ N] , d[ N] , where[ N] , tot[ N] ;
struct node{
int u, v, w, nxt;
} e[ N] ;
void add ( int u, int v, int w) {
e[ ++ cnt] . u= u; e[ cnt] . v= v; e[ cnt] . w= w;
e[ cnt] . nxt= first[ u] ; first[ u] = cnt;
}
void dijkstra ( int s) {
memset ( vis, 0 , sizeof ( vis) ) ;
memset ( dis, 0x3f , sizeof ( dis) ) ;
dis[ s] = 0 ;
priority_queue< TQX, vector< TQX> , greater< TQX> > q;
q. push ( make_pair ( dis[ s] , s) ) ;
while ( ! q. empty ( ) ) {
TQX t= q. top ( ) ; q. pop ( ) ;
int d= t. first, u= t. second;
if ( vis[ u] ) continue ;
vis[ u] = 1 ;
for ( int i= first[ u] ; i; i= e[ i] . nxt) {
int v= e[ i] . v;
if ( d+ e[ i] . w== dis[ v] ) tot[ v] ++ ;
if ( d+ e[ i] . w< dis[ v] ) {
tot[ v] = 1 ;
dis[ v] = d+ e[ i] . w;
q. push ( make_pair ( dis[ v] , v) ) ;
}
}
}
}
inline int read ( ) {
int x= 0 , f= 1 ; char ch= getchar ( ) ;
while ( ch< '0' || ch> '9' ) { if ( ch== '-' ) f= - 1 ; ch= getchar ( ) ; }
while ( '0' <= ch&& ch<= '9' ) { x= ( x<< 3 ) + ( x<< 1 ) + ( ch^ 48 ) ; ch= getchar ( ) ; }
return x* f;
}
int main ( ) {
n= read ( ) ; m= read ( ) ; k= read ( ) ;
for ( int i= 1 ; i<= m; i++ ) {
int u= read ( ) , v= read ( ) , w= read ( ) ;
add ( u, v, w) ;
add ( v, u, w) ;
memset ( val, - 1 , sizeof ( val) ) ;
for ( int i= 1 ; i<= k; i++ ) {
int v= read ( ) , w= read ( ) ;
add ( 1 , v, w) ;
d[ cnt] = 1 ;
val[ i] = w;
where[ i] = v;
add ( v, 1 , w) ;
d[ cnt] = 1 ;
}
dijkstra ( 1 ) ;
for ( int i= 1 ; i<= k; i++ ) {
int t= where[ i] , w= val[ i] ;
if ( dis[ t] < w) ans++ ;
if ( dis[ t] == w) {
if ( tot[ t] > 1 ) {
ans++ ;
tot[ t] -- ;
}
}
}
cout<< ans;
return 0 ;
}