码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 757F

时间:2017-12-15 11:10:18      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:bsp   begin   efi   main   getc   inf   long   pre   space   

最短路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

标签:bsp   begin   efi   main   getc   inf   long   pre   space   

原文地址:http://www.cnblogs.com/Mnirvana/p/8041887.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!