Jzzhu and Cities

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\n",ans);
112    }
113 }
View Code

posted on 2014-07-20 15:59  天依蓝  阅读(487)  评论(0编辑  收藏  举报

导航