關鍵結點

一個含有nn個結點mm條邊的無向有權圖,判斷每個結點是否在從11nn的最短路徑上

輸入描述
第一行輸入一個整數TT,代表有TT組測試數據 對於每一組測試數據,第一行有22個整數n,mn,m,接下來mm行每行有33個整數xi,yi,wix_i,y_i,w_ix ,表示xxyy之間有一條權值爲wiw_i 的邊

輸出描述
對於每組測試數據,在一行中輸出nn個整數,第ii個整數代表ii號結點的關鍵性
00代表該結點不可能出現在從11nn的最短路徑上
11代表該結點出現在所有從11nn的最短路徑上
22代表該結點出現在部分從11nn的最短路徑上

數據範圍
1T10001≤T≤1000
2n10002≤n≤1000
n1mmin(n×(n1)2,2105)n-1≤m≤\min(\dfrac{n\times(n-1)}{2}, 2\cdot{10}^5)
1wi1081≤w_i≤10^8
n2105\sum{n}≤2\cdot{10}^5
m2105\sum{m}≤2\cdot{10}^5
保證無重邊無自環且連通

輸出時每行末尾的多餘空格,不影響答案正確性

樣例輸入
2
6 7
1 2 1
2 3 1
2 4 1
2 5 2
3 5 1
4 5 2
5 6 1
4 6
1 2 1
1 3 1
1 4 2
2 3 1
2 4 1
3 4 1
樣例輸出
1 1 2 0 1 1
1 2 2 1

樣例解釋
對於第一組樣例的解釋:

Image

對於第二組樣例的解釋:

Image

紅點表示一定不在最短路徑上 綠點表示在所有最短路徑上 藍點表示在一部分最短路徑上

分別從節點11nn求單元最短路,得到每個點到節點11nn的最距離d1d1d2d2
ans[i]ans[i]存儲ii號節點的類型,初始化爲0。
對於任意一邊ex,ye_{x,y},滿足d1[x]<d1[y]d1[x]<d1[y]d1[x]+dx,y+d2[y]=a1[n]d1[x]+d_{x,y}+d2[y]=a1[n],則該邊在最短路徑上,因此令ans[x]=ans[y]=2ans[x]=ans[y]=2
將所有此類邊建圖,在該圖上求割點,令割點iians[i]=2ans[i]=2
最後要單獨令ans[1]=ans[n]=1ans[1]=ans[n]=1
求最短路複雜度爲O(nlogm)O(nlogm),Tarjan求割點複雜度爲O(n)O(n),因此總體時間複雜度爲O(nlogm)O(nlogm)

#include<bits/stdc++.h>

#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define sc(a) scahf("%c",&a);
#define ss(a) scanf("%s",a)
#define pi(a) printf("%d\n",a)
#define pl(a) printf("%lld\n",a)
#define pc(a) putchar(a)
#define ms(a) memset(a,0,sizeof(a))
#define repi(i, a, b) for(register int i=a;i<=b;++i)
#define repd(i, a, b) for(register int i=a;i>=b;--i)
#define reps(s) for(register int i=head[s];i;i=Next[i])
#define ll long long
#define ull unsigned long long
#define vi vector<int>
#define pii pair<int,int>
#define mii unordered_map<int,int>
#define msi unordered_map<string,int>
#define lowbit(x) ((x)&(-(x)))
#define ce(i, r) i==r?'\n':' '
#define pb push_back
#define fi first
#define se second
#define INF 0x3f3f3f3f
#define pr(x) cout<<#x<<": "<<x<<endl
using namespace std;

inline int qr() {
    int f = 0, fu = 1;
    char c = getchar();
    while (c < '0' || c > '9') {
        if (c == '-')fu = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9') {
        f = (f << 3) + (f << 1) + c - 48;
        c = getchar();
    }
    return f * fu;
}

const int N = 1e3 + 10, M = 2e5 + 10;
int head[N], ver[M << 1], Next[M << 1], edge[M << 1], tot;
int n, m, T, dfn[N], low[N], num, ans[N];
ll d1[N], d2[N];
bool v[N];
int hc[N], vc[M << 1], nc[M << 1], tc;

inline void add(int x, int y, int z) {
    ver[++tot] = y;
    Next[tot] = head[x];
    edge[tot] = z;
    head[x] = tot;
}

inline void add_c(int x, int y) {
    vc[++tc] = y;
    nc[tc] = hc[x];
    hc[x] = tc;
}

inline void dijkstra1() {
    repi(i, 1, n)v[i] = false, d1[i] = 4e18;
    d1[1] = 0;
    priority_queue<pair<ll, int> > q;
    q.push(make_pair(0, 1));
    while (!q.empty()) {
        int x = q.top().second;
        q.pop();
        if (v[x]) continue;
        v[x] = true;
        reps(x) {
            int y = ver[i], z = edge[i];
            if (d1[y] > d1[x] + z) {
                d1[y] = d1[x] + z;
                q.push(make_pair(-d1[y], y));
            }
        }
    }
}

inline void dijkstra2() {
    repi(i, 1, n)v[i] = false, d2[i] = 4e18;
    d2[n] = 0;
    priority_queue<pair<ll, int> > q;
    q.push(make_pair(0, n));
    while (!q.empty()) {
        int x = q.top().second;
        q.pop();
        if (v[x]) continue;
        v[x] = true;
        reps(x) {
            int y = ver[i], z = edge[i];
            if (d2[y] > d2[x] + z) {
                d2[y] = d2[x] + z;
                q.push(make_pair(-d2[y], y));
            }
        }
    }
}

inline void build() {
    for (int i = 1; i < tot; i += 2) {
        int x = ver[i], y = ver[i + 1], z = edge[i];
        if (d1[x] > d1[y])swap(x, y);
        if (d1[x] + z + d2[y] == d1[n])
            add_c(x, y), add_c(y, x), ans[x] = ans[y] = 2;
    }
}

void tarjan(int x) {
    dfn[x] = low[x] = ++num;
    int flag = 0;
    for (int i = hc[x]; i; i = nc[i]) {
        int y = vc[i];
        if (!dfn[y]) {
            tarjan(y);
            low[x] = min(low[x], low[y]);
            if (low[y] >= dfn[x]) {
                flag++;
                if (x != 1 || flag > 1)ans[x] = 1;
            }
        } else low[x] = min(low[x], dfn[y]);
    }
}

int main() {
    T = qr();
    while (T--) {
        n = qr(), m = qr();
        repi(i, 1, n)head[i] = 0;
        tot = 0;
        while (m--) {
            int x = qr(), y = qr(), z = qr();
            add(x, y, z), add(y, x, z);
        }
        dijkstra1(), dijkstra2();
        repi(i, 1, n)hc[i] = ans[i] = dfn[i] = low[i] = 0;
        tc = num = 0;
        build();
        tarjan(1);
        ans[n] = ans[1] = 1;
        repi(i, 1, n)printf("%d%c", ans[i], ce(i, n));
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章