UESTC 1639 雲中誰寄錦書來?雁字回時,月滿西樓

題目連接:http://acm.uestc.edu.cn/#/problem/show/1639c++

題意:
在n個點m條邊的無向圖上,有k個出口
從起點出發,每到一個點(包括起點),該點連出的邊中有d條會被封鎖
求最壞狀況下到達出口的最短路
數據範圍:
1<=n<=100000
1<=m<=1000000web

題解:算法

Dijkstra拓展
因爲求最壞狀況下的最短路,對於每一個點,顯然最優的前d條邊不能走。
對於邊u->v,必然要先獲得v到出口的最壞狀況下的最短路才能獲得u通過該邊再到出口的最壞狀況下的最短路,svg

也就是該邊對於u的價值,因此要從出口往回考慮。
令f[i]表示i到出口的最壞狀況下的最短路,同dijkstra算法同樣,每一個點i能夠分爲f[i]已肯定的和f[i]未肯定的
初始時天然是對於每一個出口x,f[x]=0已肯定。
對於f[v]已肯定的點v,將邊權爲w的邊u->v以f[v]+w爲關鍵字加入小根堆中。
對於每一個點i還要記錄cnt[i]=k,表示到i後,i連出的最優的前k條邊已被封鎖。
每次取出堆頂對應的邊u->v(若f[u]已肯定直接彈出)則該邊爲u連出的(除已被封鎖的邊外)最優的邊
若cnt[u]ui

//UESTC 1639

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
const int maxm = 1e6+7;
const int inf = 0x3f3f3f3f;
vector <pair<int,int> > G[maxn];
int dis[maxn], vis[maxn], cnt[maxn];
priority_queue <pair<int,int>, vector<pair<int, int> > , greater<pair<int, int> > >pq;
int u, v, w, k, d, n, m, len;
void Dij()
{
    memset(vis, 0, sizeof(vis));
    while(!pq.empty()){
        u = pq.top().second;
        w = pq.top().first;
        pq.pop();
        if(vis[u]) continue;
        if(cnt[u] == d){
            dis[u] = w;
            vis[u] = 1;
        }
        else{
            cnt[u]++;
            continue;
        }
        for(int i = 0; i < (int)G[u].size(); i++){
            v = G[u][i].second;
            len = G[u][i].first;
            if(dis[v] > len + w){
                pq.push(make_pair(len+w, v));
            }
        }
    }
}
int main()
{
    while(~scanf("%d %d %d %d", &n,&m,&k,&d))
    {
        while(!pq.empty()) pq.pop();
        for(int i=0; i<=n; i++) dis[i]=inf;
        memset(cnt, 0, sizeof(cnt));
        for(int i=0; i<maxn; i++) G[i].clear();
        for(int i=1; i<=m; i++){
            scanf("%d %d %d", &u,&v,&w);
            G[u].push_back(make_pair(w, v));
            G[v].push_back(make_pair(w, u));
        }
        while(k--){
            scanf("%d", &u);
            cnt[u] = d;
            dis[u] = 0;
            pq.push(make_pair(0, u));
        }
        Dij();
        if(dis[0]==inf) dis[0]=-1;
        printf("%d\n", dis[0]);
    }
    return 0;
}