zoukankan      html  css  js  c++  java
  • OVOO

    题目描述:

    $zhx$有一个棵$n$个点的树,每条边有个权值。

    定义一个连通块为一个点集与使这些点连通的所有边(这些点必须连通)。

    定义一个连通块的权值为这个连通块的边权和(如果一个连通块只包含一个点,那么它的权值为$0$)。

    $zhx$想找一个包含$1$号点的连通块送给他的妹子,所以他希望你求出包含$1$号点的所有连通块中权值第$k$小的连通块的权值。

    题解:

    非常裸的可持久化可并堆。

    经典的$k$短路要求维护绕多远+终点,而它维护总边权+可选边集。

    维护边集时需要可持久化可并堆。

    还是经典操作,要么扔掉上一条边换上次优,要么在边集中找一个最优然后更新边集。

    代码:

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 100050;
    const int MOD = 998244353;
    const int M = 50*N;
    typedef long long ll;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n,k,rt[N],wy[M];
    ll ww[M];
    struct edc
    {
        int x;
        ll d;
        edc(){}
        edc(int x,ll d):x(x),d(d){}
        friend bool operator < (edc a,edc b)
        {
            return a.d>b.d;
        }
    }tp;
    int tot,tw;
    struct node
    {
        int ls,rs,dis,tl;
        ll v;
    }p[M];
    int merge1(int x,int y)
    {
        if(!x||!y)return x+y;
        if(p[x].v>p[y].v)swap(x,y);
        p[x].rs = merge1(p[x].rs,y);
        if(p[p[x].ls].dis<p[p[x].rs].dis)swap(p[x].ls,p[x].rs);
        p[x].dis=p[p[x].rs].dis+1;
        return x;
    }
    int merge(int x,int y)
    {
        if(!x||!y)return x+y;
        if(p[x].v>p[y].v)swap(x,y);
        int u = ++tot;
        p[u] = p[x],p[u].rs = merge(p[u].rs,y);
        if(p[p[u].ls].dis<p[p[u].rs].dis)swap(p[u].ls,p[u].rs);
        p[u].dis = p[p[u].rs].dis+1;
        return u;
    }
    priority_queue<edc>q;
    ll ans;
    int main()
    {
        freopen("tt.in","r",stdin);
        read(n),read(k);
        for(int f,w,i=1;i<n;i++)
        {
            read(f),read(w);
            p[++tot].dis=1,p[tot].tl=i+1,p[tot].v=w;
            rt[f] = merge1(rt[f],tot);
        }
        k--;
        tw=1;
        ww[tw] = p[rt[1]].v;
        wy[tw] = rt[1];
        q.push(edc(1,ww[1]));
        while(k&&!q.empty())
        {
            tp = q.top();
            q.pop();
            k--;
            int u = tp.x;
            ans = ww[u];
            if(!k)break;
            int ls = p[wy[u]].ls,rs = p[wy[u]].rs;
            int tmp = merge(ls,rs);
            if(tmp)
            {
                tw++;
                ww[tw] = ww[u]-p[wy[u]].v+p[tmp].v;
                wy[tw] = tmp;
                q.push(edc(tw,ww[tw]));
            }
            tw++;
            wy[tw] = merge(tmp,rt[p[wy[u]].tl]);
            ww[tw] = ww[u]+p[wy[tw]].v;
            if(wy[tw])q.push(edc(tw,ww[tw]));
        }
        printf("%lld
    ",ans%MOD);
        return 0;
    }
  • 相关阅读:
    Asp.net routing vs Url rewriting
    How to combine WCF Route and MVC Route to work together.
    Servlets beat CGI
    What if you encounter a problem when consume your WCF service ? How to Diagnostic it ?
    uva 4965 Sum the Square
    zoj 3633 Alice's present
    4966 Normalized Form
    ZOJ 3015 Collision Ball Game
    二分图 最小路径覆盖
    uva 2696 Air Raid
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10295284.html
Copyright © 2011-2022 走看看