CF449B Jzzhu and Cities (最短路)

CF449B CF450D

http://codeforces.com/contest/450/problem/D

http://codeforces.com/contest/449/problem/B

Codeforces Round #257 (Div. 2) D

Codeforces Round #257 (Div. 1) B

D. Jzzhu and Cities
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Jzzhu is the president of country A. There are n cities numbered from 1 to n in his country. City 1 is the capital of A. Also there are m roads connecting the cities. One can go from city ui to vi (and vise versa) using the i-th road, the length of this road is xi. Finally, there are k train routes in the country. One can use the i-th train route to go from capital of the country to city si (and vise versa), the length of this route is yi.

Jzzhu doesn't want to waste the money of the country, so he is going to close some of the train routes. Please tell Jzzhu the maximum number of the train routes which can be closed under the following condition: the length of the shortest path from every city to the capital mustn't change.

Input

The first line contains three integers n, m, k (2 ≤ n ≤ 105; 1 ≤ m ≤ 3·105; 1 ≤ k ≤ 105).

Each of the next m lines contains three integers ui, vi, xi (1 ≤ ui, vi ≤ nui ≠ vi; 1 ≤ xi ≤ 109).

Each of the next k lines contains two integers si and yi (2 ≤ si ≤ n; 1 ≤ yi ≤ 109).

It is guaranteed that there is at least one way from every city to the capital. Note, that there can be multiple roads between two cities. Also, there can be multiple routes going to the same city from the capital.

Output

Output a single integer representing the maximum number of the train routes which can be closed.

Sample test(s)
Input
5 5 3
1 2 1
2 3 2
1 3 3
3 4 4
1 5 5
3 5
4 5
5 5
Output
2
Input
2 2 3
1 2 2
2 1 3
2 1
2 2
2 3
Output
2

题意:有n个城市,1是首都。给出m条有权无向边(公路),k条由1连接到某个城市的有权无向边(铁路),求在保持首都到各个城市的最短路长度不变的情况下,最多能炸掉多少条铁路。

 

题解:首都到达同一个城市的铁路只保留最短的,然后进行最短路并统计某个顶点最短路的更新次数,最后只保留长度等于最短路且更新次数为1(只有这一种最短路)的铁路。

设一个c[i]记录i点的更新次数,初始c[首都]为1,其他为0。更新的时候dij和spfa不是小于才更新嘛,小于的时候就c[新点]=c[当前点],等于的时候就c[新点]+=c[当前点],这样c[i]就是最短路的更新次数(最短路的方案数)。

注意CF可是大家都能出数据的,有人出了个卡SPFA的数据,我都吓尿了。可以给SPFA加SLF优化过。有人用优先队列过的,因为还好没人出卡优先队列SPFA的数据…

代码:

  1 //#pragma comment(linker, "/STACK:102400000,102400000")
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<iostream>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<cmath>
  8 #include<map>
  9 #include<set>
 10 #include<stack>
 11 #include<queue>
 12 using namespace std;
 13 #define ll long long
 14 #define usll unsigned ll
 15 #define mz(array) memset(array, 0, sizeof(array))
 16 #define minf(array) memset(array, 0x3f, sizeof(array))
 17 #define REP(i,n) for(i=0;i<(n);i++)
 18 #define FOR(i,x,n) for(i=(x);i<=(n);i++)
 19 #define RD(x) scanf("%d",&x)
 20 #define RD2(x,y) scanf("%d%d",&x,&y)
 21 #define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
 22 #define WN(x) prllf("%d\n",x);
 23 #define RE  freopen("D.in","r",stdin)
 24 #define WE  freopen("1biao.out","w",stdout)
 25 #define mp make_pair
 26 #define pb push_back
 27 
 28 const ll INF=1LL<<60;
 29 
 30 const int maxn=111111;
 31 const int maxm=888888;
 32 struct edge {
 33     int v,next;
 34     ll w;
 35 } e[maxm];///边表
 36 int head[maxn],en;
 37 
 38 void add(int x,int y,ll z) {
 39     e[en].w=z;
 40     e[en].v=y;
 41     e[en].next=head[x];
 42     head[x]=en++;
 43 }
 44 
 45 int n,m,k;
 46 ll g[maxn];
 47 bool f[maxn];///入队标志
 48 int b[maxn], c[maxn];
 49 ll d[maxn];///b为循环队列,d为起点到各点的最短路长度
 50 void spfa() { ///0~n-1,共n个点,起点为st
 51     int i,k;
 52     int st=0, l=0, r=1;
 53     memset(f,0,sizeof(f));
 54     memset(b,0,sizeof(b));
 55     for(i=0; i<n; i++)
 56         d[i]=INF;
 57     b[0]=st;
 58     f[st]=1;
 59     d[st]=0;
 60     c[st]=1;
 61     while(l!=r) {
 62         k=b[l++];
 63         l%=n;
 64         for(i=head[k]; i!=-1; i=e[i].next)
 65             if (d[k]+e[i].w < d[e[i].v]) {
 66                 d[e[i].v]=d[k] + e[i].w;
 67                 c[e[i].v]=c[k];
 68                 if (!f[e[i].v]) {
 69                     if(d[e[i].v]>d[b[l]]) {///SLF优化,这题卡没优化的SPFA……
 70                         b[r++]=e[i].v;
 71                         r%=n;
 72                     } else {
 73                         l--;
 74                         if(l==-1)l=n-1;
 75                         b[l]=e[i].v;
 76                     }
 77                     f[e[i].v]=1;
 78                 }
 79             } else if(d[k]+e[i].w == d[e[i].v])
 80                 c[e[i].v]+=c[k];
 81         f[k]=0;
 82     }
 83 }
 84 
 85 void init() {
 86     memset(head,-1,sizeof(head));
 87     en=0;
 88 }
 89 
 90 int main() {
 91     int i,x,y;
 92     ll z;
 93     while(scanf("%d%d%d",&n,&m,&k)!=EOF) {
 94         init();
 95         REP(i,m) {
 96             scanf("%d%d%I64d",&x,&y,&z);
 97             x--;
 98             y--;
 99             add(x,y,z);
100             add(y,x,z);
101         }
102 
103         REP(i,n) g[i]=INF;
104 
105         REP(i,k) {
106             scanf("%d%I64d",&x,&z);
107             x--;
108             if(z<g[x]) g[x]=z;
109         }
110 
111         REP(i,n)
112             if(g[i]!=INF) {
113                 add(0,i,g[i]);
114                 add(i,0,g[i]);
115             }
116 
117         memset(c,0,sizeof(c));
118         spfa();
119 
120         int remain=0;
121         REP(i,n)
122             if(g[i]!=INF && c[i]==1 && d[i]==g[i])
123                 remain++;
124         printf("%d\n",k-remain);
125     }
126     return 0;
127 }
View Code

 

posted @ 2014-08-19 10:43  带鱼Yuiffy  阅读(572)  评论(0编辑  收藏  举报