• COJ500 杨老师的路径规划(MST) (我是认真的)


    用LCT来维护生成树,动态加边(s,t,w)时,新建节点x,权值为边权w。

    1.若s与t不连通,则连接s-x,x-t,答案+w

    2.若s与t连通,找出s-t路径上的最大权w2,若w<w2,删除w2的连边,连接s-x,x-t,答案+w-w2

    太水了是不是!

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define lc ch[x][0]
    #define rc ch[x][1]
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=10010;
    int ch[maxn][2],fa[maxn],pre[maxn],flip[maxn],mx[maxn],v[maxn];
    void maintain(int x)
    {
        mx[x]=x;
        if(v[mx[lc]]>v[mx[x]]) mx[x]=mx[lc];
        if(v[mx[rc]]>v[mx[x]]) mx[x]=mx[rc];
    }
    void pushdown(int x)
    {
        if(!flip[x]) return;
        swap(lc,rc);flip[lc]^=1;flip[rc]^=1;flip[x]=0;
    }
    void rotate(int x)
    {
        int y=pre[x],z=pre[y],d=ch[y][0]==x;
        ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y;
        ch[z][ch[z][1]==y]=x;pre[x]=z;
        ch[x][d]=y;pre[y]=x;maintain(y);
    }
    int q[maxn],top;
    void splay(int x)
    {
        for(int i=x;i;i=pre[i]) q[++top]=i;
        if(top!=1) fa[x]=fa[q[top]];
        while(top) pushdown(q[top--]);
        while(pre[x]) rotate(x);
        maintain(x);
    }
    void access(int x)
    {
        for(int y=0;x;x=fa[x])
        {
            splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x;
            ch[x][1]=y;pre[y]=x;
            maintain(y=x);
        }
    }
    void makeroot(int x) {access(x);splay(x);flip[x]^=1;}
    void link(int x,int y) {makeroot(x);fa[x]=y;}
    void cut(int x,int y) {makeroot(x);access(y);splay(y);ch[y][0]=pre[ch[y][0]]=0;maintain(x);}
    int find(int x) {access(x);splay(x);while(ch[x][0]) x=ch[x][0];return x;}
    int query(int x,int y)
    {
        makeroot(x);access(y);splay(y);return mx[y];
    }
    int s[maxn],t[maxn];
    int main()
    {
        int n=read(),m=n*(n-1)>>1,ToT=n,ret=0;
        for(int i=1;i<=m;i++)
        {
            s[i]=read(),t[i]=read(),v[++ToT]=read();
            if(find(s[i])!=find(t[i])) link(s[i],ToT),link(ToT,t[i]),ret+=v[ToT];
            else
            {
                int p=query(s[i],t[i]);if(v[p]>v[ToT])
                {
                    ret+=v[ToT]-v[p];
                    cut(p,s[p-n]);cut(p,t[p-n]);
                    link(s[i],ToT);link(ToT,t[i]);
                }
            }
        }
        printf("%d
    ",ret);
        return 0;
    }
    View Code
  • 相关阅读:
    P2761 软件补丁问题
    CF1335F Robots on a Grid
    [bzoj2088]P3505 [POI2010]TEL-Teleportation
    CF1335E Three Blocks Palindrome
    P3831 [SHOI2012]回家的路
    P4568 [JLOI2011]飞行路线(分层图)
    P4774 [NOI2018]屠龙勇士
    P2480 [SDOI2010]古代猪文
    CF #632 (Div. 2) 对应题号CF1333
    BSGS 和扩展
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/4590667.html
Copyright © 2020-2023  润新知