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 secondsmemory limit per test
256 megabytesinput
standard inputoutput
standard outputJzzhu 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 ≤ n; ui ≠ 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 Output
2 Input
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 }