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\n",ret);
    return 0;
}
View Code

 

posted @ 2015-06-20 16:06  wzj_is_a_juruo  阅读(322)  评论(0编辑  收藏  举报