ICPC NEAU Programming Contest 2020 K. 關鍵結點(最短路+割點)

在這裏插入圖片描述

思路:
判斷一個點在不在最短路上好辦,就是從這個點到1的最短距離加上到n的最短距離加起來
判斷是不是在所有最短路上,則把所有最短路邊加上建一個新圖,如果新圖上這個點是割點,那明顯所有最短路都經過了這個點

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
#include <map>
#include <string>

using namespace std;

typedef long long ll;

const int maxn = 2e5 + 7;
const int MX = 1005;
const ll INF = 1e18;
int head[MX],nex[maxn * 2],to[maxn * 2],val[maxn * 2],tot;;
int Head[MX],Nex[maxn * 2],To[maxn * 2],Val[maxn * 2],Tot;
ll dis1[MX],dis2[MX];
int vis[MX],ans[MX],dfn[MX],low[MX],dfs_clock,root;
bool cut[MX];
int n,m;

void add(int x,int y,int z) {
    to[++tot] = y;
    nex[tot] = head[x];
    val[tot] = z;
    head[x] = tot;
}

void Add(int x,int y,int z) {
    To[++Tot] = y;
    Nex[Tot] = Head[x];
    Val[Tot] = z;
    Head[x] = Tot;
}

void init() {
    memset(head,0,sizeof(head));
    memset(Head,0,sizeof(Head));
    tot = Tot = 0;
    memset(ans,0,sizeof(ans));
    memset(dfn,0,sizeof(dfn));
    memset(low,0,sizeof(low));
    memset(cut,false,sizeof(cut));
    dfs_clock = 0;
    
}

void dijkstra(int sta,ll *dis) {
    for(int i = 1;i <= n;i++) {
        dis[i] = INF;
        vis[i] = 0;
    }
    priority_queue<pair<int,int> >Q;
    dis[sta] = 0;
    Q.push({0,sta});
    
    while(!Q.empty()) {
        pair<int,int>now = Q.top();Q.pop();
        int u = now.second;
        vis[u] = 1;
        for(int i = head[u];i;i = nex[i]) {
            int v = to[i],w = val[i];
            if(vis[v]) continue;
            if(dis[v] > dis[u] + w) {
                dis[v] = dis[u] + w;
                Q.push({-dis[v],v});
            }
        }
    }
}

void tarjan(int x) {
    dfn[x] = low[x] = ++dfs_clock;
    int flag = 0;
    for(int i = Head[x];i;i = Nex[i]) {
        int y = To[i];
        if(!dfn[y]) {
            tarjan(y);
            low[x] = min(low[x],low[y]);
            if(low[y] >= dfn[x]) {
                flag++;
                if(x != root || flag > 1) cut[x] = true;
            }
        }
        else {
            low[x] = min(low[x],dfn[y]);
        }
    }
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        init();
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= m;i++) {
            int x,y,z;scanf("%d%d%d",&x,&y,&z);
            add(x,y,z);add(y,x,z);
        }
        
        dijkstra(1,dis1);
        dijkstra(n,dis2);
        
        ll min_dis = dis1[n];
        for(int i = 1;i <= n;i++) {
            if(dis1[i] + dis2[i] == min_dis) {
                ans[i] = 2;
            }
            else ans[i] = 0;
            
            for(int j = head[i];j;j = nex[j]) {
                int v = to[j],w = val[j];
                if(dis1[i] + w + dis2[v] == min_dis) {
                    Add(i,v,w);
                    Add(v,i,w);
                }
            }
        }
        
        for(int i = 1;i <= n;i++) {
            if(!dfn[i]) root = i,tarjan(i);
        }
        for(int i = 1;i <= n;i++) {
            if((cut[i] && ans[i] == 2) || i == 1 || i == n) ans[i] = 1;
            printf("%d ",ans[i]);
        }
        printf("\n");
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章