zoukankan      html  css  js  c++  java
  • bzoj4016 [FJOI2014]最短路径树问题

    题目描述

    题解:

    先要建一棵字典序最小的最短路树。

    怎么建呢?

    想起后缀数组,然后突然意识到可以按字典序依次搜索每一个点。

    具体操作就是搜索时将可以转移到的点记录一下,然后按字典序排序,然后一个一个走。

    这样最短路径树就建好了。

    然后就是点分治+桶。

    代码:

    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 30050
    #define M 60050
    #define ll long long
    inline int rd()
    {
        int f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();}
        return f*c;
    }
    const int inf = 0x3f3f3f3f;
    int n,m,K,hd[N],ct,hed[N],cnt;
    struct EG
    {
        int to,nxt,v;
    }e1[2*M],e[2*N];
    void ae1(int f,int t,int v)
    {
        e1[++ct].to = t;
        e1[ct].nxt = hd[f];
        e1[ct].v = v;
        hd[f] = ct;
    }
    void ae(int f,int t,int v)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        e[cnt].v = v;
        hed[f] = cnt;
    }
    int dis[N];
    bool vis[N];
    struct Pair
    {
        int x,d;
        Pair(){}
        Pair(int x,int d):x(x),d(d){}
        friend bool operator < (Pair a,Pair b)
        {
            return a.d > b.d;
        }
    }tp;
    void dij()
    {
        memset(dis,0x3f,sizeof(dis));
        dis[1]=0;
        priority_queue<Pair>q;
        q.push(Pair(1,0));
        while(!q.empty())
        {
            tp = q.top();
            q.pop();
            int u = tp.x;
            if(vis[u])continue;
            vis[u]=1;
            for(int j=hd[u];j;j=e1[j].nxt)
            {
                int to = e1[j].to;
                if(dis[to]>dis[u]+e1[j].v)
                {
                    dis[to] = dis[u]+e1[j].v;
                    q.push(Pair(to,dis[to]));
                }
            }
        }
    }
    int fa[N];
    void build(int u)
    {
        vector<int>ve;
        for(int j=hd[u];j;j=e1[j].nxt)
        {
            int to = e1[j].to;
            if(!fa[to]&&dis[to]==dis[u]+e1[j].v)
            {
                fa[to] = u;
                ve.push_back(to);
                ae(u,to,e1[j].v);
                ae(to,u,e1[j].v);
            }
        }
        sort(ve.begin(),ve.end());
        for(int i=0;i<ve.size();i++)
            build(ve[i]);
    }
    int rt,sum,mrk[N],w[N],siz[N];
    void get_rt(int u,int fa)
    {
        siz[u] = 1;w[u] = 0;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to]||to==fa)continue;
            get_rt(to,u);
            siz[u]+=siz[to];
            if(siz[to]>w[u])w[u] = siz[to];
        }
        w[u] = max(w[u],sum-siz[u]);
        if(w[u]<w[rt])rt=u;
    }
    int f[N],g[N],max_dep;
    ll sf[N],sg[N],as1,as2;
    void dfs(int u,int fa,int dep,ll ds)
    {
        if(dep>=K)return ;
        if(dep==K-1)
        {
            if(as1<ds)
            {
                as1 = ds;
                as2 = 1;
            }else if(as1==ds)
            {
                as2++;
            }
            return ;
        }
        if(f[dep]<ds)f[dep]=ds,sf[dep]=1;
        else if(f[dep]==ds)sf[dep]++;
        max_dep = max(max_dep,dep);
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==fa||mrk[to])continue;
            dfs(to,u,dep+1,ds+e[j].v);
        }
    }
    void work(int u)
    {
        mrk[u] = 1;int mx = 0;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            max_dep = 0;
            dfs(to,u,1,e[j].v);
            mx = max(mx,max_dep);
            for(int i=1;i<=max_dep;i++)
            {
                if(g[K-i-1]!=-1)
                {
                    if(f[i]+g[K-i-1]>as1)
                    {
                        as1 = f[i]+g[K-i-1];
                        as2 = sf[i]*sg[K-i-1];
                    }else if(f[i]+g[K-i-1]==as1)
                    {
                        as2 += sf[i]*sg[K-i-1];
                    }
                }
            }
            for(int i=1;i<=max_dep;i++)
            {
                if(f[i]>g[i])
                {
                    g[i]=f[i];
                    sg[i] = sf[i];
                }else if(f[i]==g[i])
                {
                    sg[i] += sf[i];
                }
                f[i] = sf[i] = 0;
            }
        }
        for(int i=1;i<=mx;i++)
            g[i]=-1,sg[i]=0;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(mrk[to])continue;
            rt = 0,sum = siz[to];
            get_rt(to,0);
            work(rt);
        }
    }
    int main()
    {
        n = rd(),m = rd(),K = rd();
        for(int f,t,v,i=1;i<=m;i++)
        {
            f = rd(),t = rd(),v = rd();
            ae1(f,t,v),ae1(t,f,v);
        }
        dij();fa[1]=-1;
        build(1);
        w[0] = inf;as1=-inf;
        memset(g,-1,sizeof(g));
        rt=0,sum=n;
        get_rt(1,0);
        work(rt);
        printf("%lld %lld
    ",as1,as2);
        return 0;
    }
  • 相关阅读:
    PAT 甲级 1132 Cut Integer (20 分)
    AcWing 7.混合背包问题
    AcWing 9. 分组背包问题
    AcWing 5. 多重背包问题 II
    AcWing 3. 完全背包问题
    AcWing 4. 多重背包问题
    AcWing 2. 01背包问题
    AcWing 875. 快速幂
    AcWing 874. 筛法求欧拉函数
    AcWing 873. 欧拉函数
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10190103.html
Copyright © 2011-2022 走看看