题意:一个图,其中一些边被打上了标记,找一个最短路树,使得树边包含的标记边最少。
思路:二维dijkstra。二维dijkstra的原理可以理解为dp,每个点的dp值都是最优的状态。转移时从最优的上一个状态进行转移。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,int> pii;
typedef pair<pii,int> piii;
const int maxn = 100005;
const int maxm = 1000005;
int tot,ver[maxm],ne[maxm],he[maxn],cost[maxm],id[maxm];
void add( int x,int y,int w,int _id ){
ver[++tot] = y;
ne[tot] = he[x];
he[x] = tot;
cost[tot] = w;
id[tot] = _id;
}
priority_queue< piii,vector< piii >,greater<piii > > que;
int vis[maxn],fa[maxn];
pii dist[maxn];
const LL inf = 0x3f3f3f3f3f3f3f3f;
void dijkstra( int s,int n ){
while( que.size() ) que.pop();
//memset( dist,0x3f,sizeof(LL)*(n+1) );
for( int i = 1;i <= n;i++ ){
dist[i] = pii( inf,2 );
}
dist[s] = pii(0,0);
que.push( piii( pii(0,0),s ) );
while( que.size() ){
int x = que.top().second;
que.pop();
if( vis[x] ) continue;
vis[x] = 1;
for( int cure = he[x];cure;cure = ne[cure] ){
int y = ver[cure];
if( vis[y] ) continue;
pii cur = pii( dist[x].first + cost[cure], id[cure] );
if( dist[y] > cur ){
dist[y] = cur;
if( id[cure] ) fa[y] = 1;
else fa[y] = 0;
que.push( make_pair( dist[y],y ) );
}
}
}
}
int main(){
int n,m,k,x,y,w;
scanf("%d%d%d",&n,&m,&k);
for( int i = 1;i <= m;i++ ){
scanf("%d%d%d",&x,&y,&w);
add( x,y,w,0 );
add( y,x,w,0 );
}
for( int i = 1;i <= k;i++ ){
scanf("%d%d",&x,&y);
add( 1,x,y,1 );
}
dijkstra( 1,n );
int ans = 0;
for( int i = 1;i <= n;i++ ){
if( fa[i] ) ans++;
}
printf("%d\n",k-ans);
return 0;
}