• ACM-ICPC (10/19)


    这两天在看虚树,的确很难理解。

    不过大致的思路就是说删掉一些没有用的点,但是仍然保持树的相对结构,树上只有两种点,一个是集合点,和一些LCA,这些LCA是为了保持树的相对结构,才留下的。

    具体做法网上说的天花乱坠,我实在是想吐槽。作为新人没有什么很好的入门资料,大佬们也是含含糊糊,就是一顿套模板了(和图论一样),反正做题也是在新树上重新DP~~~

    附上BZOJ2286的模板例子,我删减了一部分。根据题意来~~~

    具体的原理我也不想管了。ヾ(◍°∇°◍)ノ゙  who care who 呢?

    #include<iostream>
    #include<set>
    #include<map>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<vector>
    #include<queue>
    #include<algorithm>
    #include<cmath>
    #include<bitset>
    #include<stack>
    #define inf 1e60
    #define pa pair<int,int>
    #define ll long long
    using namespace std;
    
    
    int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    
    int bin[20];
    int n,m,cnt,ind,top;
    int last[250005],last2[250005],fa[250005][20];
    ll mn[250005],f[250005];
    int h[250005],mark[250005],deep[250005];
    int st[250005];
    
    struct edge{
        int to,next,v;
    }e[500005],ed[500005];
    
    void insert(int u,int v,int w)
    {
        e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
        e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w;
    }
    
    void insert2(int u,int v)   //单向边了,也可以是双向的。
    {
    
        if(u==v)return;
        printf("%d--->%d
    ",u,v);
        ed[++cnt].to=v;ed[cnt].next=last2[u];last2[u]=cnt;
    }
    
    bool cmp(int a,int b)
    {
        return mark[a]<mark[b];
    }
    
    void pre(int x)
    {
        mark[x]=++ind;
        for(int i=1;bin[i]<=deep[x];i++)
            fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=last[x];i;i=e[i].next)
            if(e[i].to!=fa[x][0])
            {
                mn[e[i].to]=min(mn[x],(ll)e[i].v);
                deep[e[i].to]=deep[x]+1;
                fa[e[i].to][0]=x;
                pre(e[i].to);
            }
    }
    
    int lca(int x,int y)
    {
        if(deep[x]<deep[y])swap(x,y);
        int t=deep[x]-deep[y];
        for(int i=0;bin[i]<=t;i++)
            if(t&bin[i])x=fa[x][i];
        for(int i=19;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        if(x==y)return x;
        return fa[x][0];
    }
    
    void dp(int x)
    {
        f[x]=mn[x];
        ll tmp=0;
        for(int i=last2[x];i;i=ed[i].next)
        {
            dp(ed[i].to);
            tmp+=f[ed[i].to];
        }
        last2[x]=0;
        if(tmp==0)f[x]=mn[x];
        else if(tmp<=f[x])f[x]=tmp;
    }
    
    void solve()
    {
        cnt=0;
        int K=read();
        for(int i=1;i<=K;i++)
            h[i]=read();
        sort(h+1,h+K+1,cmp);
        int tot=K;
    //    h[++tot]=h[1];
    //    for(int i=2;i<=K;i++) {
    //        int tmp = lca(h[tot],h[i]);
    //        if(lca(h[tot],h[i])!=h[tot])
    //            h[++tot]=h[i];
    //    }
    
    
        st[++top]=1;        //top栈指针
        for(int i=1;i<=tot;i++)
        {
            int now=h[i],f=lca(now,st[top]);
            while(1)
            {
                if(deep[f]>=deep[st[top-1]])
                {
                    insert2(f,st[top--]);
                    if(st[top]!=f)st[++top]=f;
                    break;
                }
                insert2(st[top-1],st[top]);top--;
            }
            if(st[top]!=now)st[++top]=now;
        }
    
        while(--top)insert2(st[top],st[top+1]);
        dp(1);
        printf("%lld
    ",f[1]);
    }
    
    
    int main()
    {
        freopen("in.txt","r",stdin);
        bin[0]=1;for(int i=1;i<20;i++)bin[i]=bin[i-1]<<1;
        n=read();
        for(int i=1;i<n;i++)
        {
            int u=read(),v=read(),w=read();
            insert(u,v,w);
        }
        mn[1]=inf;pre(1);
        m=read();
        for(int i=1;i<=m;i++)
            solve();
        return 0;
    }

    最近两天的训练效果不咋样,心思太杂了,我得调整调整,好好A题吧~~~

    具体方案就是看论文,做经典题吧~~~

    详细论文:

    2015集训队论文集

    《浅谈字符串匹配的几种方式》

    《后缀数组》

    《后缀自动机及其应用》

    《生成函数的运用与组合计数问题》

    2016集训队论文

    《网络流的一些建模方法》

    《再探快速傅里叶变换》

    DP专题:

    http://www.cnblogs.com/qscqesze/p/4614733.html

  • 相关阅读:
    python
    在liunx环境下安装python
    解决用navicate远程连接数据库出现1045
    mysql的监控及优化
    mysql基础
    linux基础学习
    Effective c++ 第一章 让自己习惯C++
    读前感
    socket编程:客户端与服务器间的连接以及各函数的用法
    生成任意区间的随机数
  • 原文地址:https://www.cnblogs.com/TreeDream/p/7694928.html
Copyright © 2020-2023  润新知