CF449B Jzzhu and Cities (最短路+思维)

这里必须要全部存图而不能直接判断原先最短路和给定特殊边的关系

因为我们如果用了某个特殊边,其实会影响到其他点最短路,使得他的最短路更小,我们直接判断,会导致本身的可以被删掉的答案,因为没用特殊边而不能删掉

所以本题的做法是,全部存下来后,记录某个点的最短路的个数

如果特殊边大于最短路,那就直接删掉

如果特殊边等于最短路,看看个数是否大于1

#include<bits/stdc++.h>
#define getsz(p) (p?p->sz:0)
using namespace std;
typedef long long ll;
typedef pair<ll,int> pll;
const int N=1e6+10;
int h[N],ne[N],e[N],idx;
ll d[N],w[N];
ll dis[N];
int st[N];
int sign[N];
int vis[N],to[N];
void add(int a,int b,int c){
    e[idx]=b,ne[idx]=h[a],w[idx]=c,h[a]=idx++;
}
void dij(){
    priority_queue<pll,vector<pll>,greater<pll>> q;
    q.push({0,1});
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    while(q.size()){
        auto t=q.top();
        q.pop();
        if(st[t.second]){

            continue;
        }
        st[t.second]=1;
        for(int i=h[t.second];i!=-1;i=ne[i]){
            int j=e[i];
            if(dis[j]>dis[t.second]+w[i]){
                vis[j]=1;
                dis[j]=dis[t.second]+w[i];
                q.push({dis[j],j});
            }
            else if(dis[j]==dis[t.second]+w[i]){
                vis[j]++;
            }
        }
    }

}
int main(){
    ios::sync_with_stdio(false);
    int n,m,k;
    cin>>n>>m>>k;
    memset(h,-1,sizeof h);
    memset(d,0x3f,sizeof d);
    int i,j;
    for(i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        add(a,b,c);
        add(b,a,c);
    }
    int cnt=0;
    for(i=1;i<=k;i++){
        int a,b;
        cin>>a>>b;
        sign[a]=1;
        to[i]=a;
        add(1,a,b);
        add(a,1,b);
        d[i]=b;
    }
    dij();
    for(i=1;i<=k;i++){
        if(d[i]>dis[to[i]]){
            cnt++;
        }
        else if(d[i]==dis[to[i]]&&vis[to[i]]>1){
            vis[to[i]]--;
            cnt++;
        }
    }
    cout<<cnt<<endl;
    return 0;
}
View Code

 

posted @ 2020-08-12 14:53  朝暮不思  阅读(179)  评论(0编辑  收藏  举报