1. 程式人生 > >codeforces 757F

codeforces 757F

amp head fin return 新的 typedef sdi c++ bits

最短路DAG + 支配樹

支配樹是一種解決必經點問題的數據結構。

在dijkstra中可以處理處拓撲序,進而建立最短路DAG

但由於求最短路時,可能會有未聯通的點,所以在用最短路求拓撲序的時候,要把被更新的點pop掉。

附代碼

#include "bits/stdc++.h"
using namespace std;
#define maxn 2222222
#define For(i ,j ,n) for(int i = j; i<=n; i++)
#define pa  pair<long long ,int> 
int n ,m ,s ,head[maxn] ,deep[maxn] ,cnt ,ord[maxn],size[maxn] ,p[maxn][22] ,maxx;
bool vis[maxn];
long long dis[maxn];
typedef long long ll;
vector <pair<int, ll> > e[maxn];
template <typename T>
void read(T &x)
{
    x = 0;char c = getchar();
    while(!isdigit(c)) c = getchar();
    while(isdigit(c)) 
    {
        x = (x<<3) + (x<<1) + c - ‘0‘;
        c = getchar();
    }
    return ;
}
const long long inf = 1ll<<60;
void dijkstra()
{
    set <pair<ll, int> > hs;
    for(int i=1; i<=n; i++) 
        dis[i] = inf;
    dis[s] = 0;
    for(int i=1; i<=n ;i++) hs.insert(make_pair(dis[i], i));
    for(int i=0; i<n; i++)
    {
        int u = (hs.begin())->second; hs.erase(hs.begin());
        ord[i] = u;
        for(int j = 0; j < e[u].size(); j++)
        {
            int v = e[u][j].first;
            if(dis[e[u][j].first] > dis[u]+e[u][j].second)
            {
                hs.erase(make_pair(dis[v], v));
                dis[e[u][j].first] = dis[u]+e[u][j].second;
                 hs.insert(make_pair(dis[v], v));
            }     
        }
    }
}

int lca(int a, int b)
{
    if(deep[a] < deep[b]) swap(a ,b);
    if(deep[a] != deep[b])
    {
        for(int i=20; i>=0; i--)
            if(deep[p[a][i]] >= deep[b])
                a = p[a][i];
    }
    if(a == b) return a;
    for(int i=20; i>=0; i--)
        if(p[a][i] != p[b][i])
        {
            a = p[a][i];
            b = p[b][i];
        }
    return p[a][0];
}

int main()
{
    cin >>n >>m >>s;
    int a ,b ,c;
    For(i ,1 ,m)
    {
         cin>>a>>b>>c;
        e[a].push_back(make_pair(b, c));
        e[b].push_back(make_pair(a, c));
    }
    dijkstra();
    p[s][0] = 0;deep[s] = 1;
     for(int i = 1; i <= n; i++)
    {
        int d = -1, u = ord[i];
        for(vector<pair<int ,long long> >::iterator iter = e[u].begin();iter!=e[u].end();iter++)
        {
            if(dis[iter->first] + iter->second == dis[u])
            {
                if(d == -1) d = iter->first;
                else d = lca(d, iter->first);
            }
        }
        p[u][0] = d; deep[u] = deep[d]+1;
        for(int j = 1; j < 21; j++) p[u][j] = p[p[u][j-1]][j-1];    //動態更新公共祖先
    }
   for(int i = 1; i <= n; i++) size[i] = 1;
    int ret = 0;
    for(int i = n-1; i >= 1; i--)       //按照拓撲序dp求最大值
    {
        int u = ord[i];
        size[p[u][0]] += size[u];
        if(dis[u] <= (1ll<<50)) ret = max(ret, size[u]);
    }
     for(int i=1; i<=n; i++)
        cout <<ord[i] <<" ";
     cout <<ret <<endl;
}

codeforces 757F