CF #257 div2D:http://codeforces.com/contest/450/problem/D
题意:给你n个城市,m条无向有权边。另外还有k条边,每条边从起到到i。求可以删除这k条边中的多少条,使得每个点到1的最短距离不变。
题解:通过这一题明白了,对于一个问题要有分析思考的能力。首先分析一下,对于城市i,(1)如果没有从1到i的特殊边(即上述k条中的一条),我们不用考虑。(2)如果有,在这之前已经求出了每个点的最短路,如果这条边的边权大于等于最短路,则可以直接删除,一不会影响本身的最短路,二不会影响别的城市,因为别的城市可以通过当前已经求得的最短路进行松弛。(3)如果这个边权边权小于最短路,那么我们把最短路路径修改为这个距离,接下就要判断,能否通过其它的点来求得当前的最短路或者更短,很明显,如果能够求得到这个距离,说明可以通过其它点来得到这个最短路,那么这一条路径可以删除了,否则就是唯一的。对于这一来说,如果用链式前向星来存图的话,我的是T了,也许是哪里没有处理好,改成Vecotr就A了。这确实是不错的题目。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 #include<vector> 7 #define INF 10000000000000000LL 8 #define ll long long 9 using namespace std; 10 const int N=1e5+4; 11 const int M=3*1e5+4; 12 int n,m,k,ans,u,v; 13 long long temp,dist1[N],dist2[N],dist3[N]; 14 bool flag[N],visit[N]; 15 struct Edge{ 16 int v; 17 ll w; 18 Edge(int vi, ll wi) : v(vi), w(wi){} 19 Edge(){} 20 }; 21 vector<Edge>G[N]; 22 void SPFA1(int u){ 23 for(int i=1;i<=n;i++){ 24 dist1[i]=INF; 25 visit[i]=0; 26 } 27 queue<int>Q; 28 dist1[u]=0; 29 visit[u]=1; 30 Q.push(u); 31 while(!Q.empty()){ 32 int v=Q.front(); 33 Q.pop(); 34 visit[v]=0; 35 for (int i = 0; i < G[v].size(); i++){ 36 int d = G[v][i].v; ll w = G[v][i].w; 37 if(dist1[d]>dist1[v]+w){ 38 dist1[d]=dist1[v]+w; 39 if(!visit[d]){ 40 Q.push(d); 41 visit[d]=1; 42 } 43 } 44 } 45 } 46 } 47 void SPFA2(int u){ 48 for(int i=1;i<=n;i++){ 49 visit[i]=0; 50 dist3[i]=INF; 51 } 52 queue<int>Q; 53 dist3[u]=0; 54 visit[u]=1; 55 Q.push(u); 56 for(int i=1;i<=n;i++){ 57 if(dist2[i]<dist1[i]){ 58 Q.push(i); 59 visit[i]=1; 60 dist3[i]=dist2[i]; 61 } 62 } 63 while(!Q.empty()){ 64 int v=Q.front(); 65 Q.pop(); 66 visit[v]=0; 67 for (int i = 0; i < G[v].size(); i++){ 68 int d = G[v][i].v; ll w = G[v][i].w; 69 if(dist3[d]>dist3[v]+w){ 70 dist3[d]=dist3[v]+w; 71 if(!visit[d]){ 72 Q.push(d); 73 visit[d]=1; 74 } 75 if(flag[d]){ 76 ans++; 77 flag[d]=0; 78 } 79 } 80 else if(dist3[d]==dist3[v]+w){ 81 if(flag[d]){ 82 ans++; 83 flag[d]=0; 84 } 85 } 86 } 87 } 88 } 89 int main(){ 90 while(~scanf("%d%d%d",&n,&m,&k)){ 91 for (int i = 0; i <= n; i++) G[i].clear(); 92 for(int i=1;i<=m;i++){ 93 scanf("%d%d%I64d",&u,&v,&temp); 94 G[u].push_back(Edge(v,temp)); 95 G[v].push_back(Edge(u,temp)); 96 } 97 SPFA1(1); 98 ans=0;memset(flag,0,sizeof(flag)); 99 for(int i=1;i<=n;i++) 100 dist2[i]=dist1[i]; 101 for(int i=1;i<=k;i++){ 102 scanf("%d%I64d",&v,&temp); 103 if(dist2[v]<=temp)ans++; 104 else{ 105 dist2[v]=temp; 106 if(flag[v])ans++; 107 flag[v]=1; 108 } 109 } 110 SPFA2(1); 111 printf("%d ",ans); 112 } 113 }