zoukankan      html  css  js  c++  java
  • 2084. Asm.Def的基本算法

    2084. Asm.Def的基本算法

    传送门

    ★☆   输入文件:asm_algo.in   输出文件:asm_algo.out   简单对比
    时间限制:1 s   内存限制:256 MB

    【题目描述】

    “有句美国俗语说,如果走起来像鸭子,叫起来像鸭子,那就是一只鸭子。”斯科特·华莱士看着Asm.Def面前屏幕上滚动的绿色字符,若有所思地说。

    “什么意思?”

    “你的数据。看上去是一棵树。”

    “按照保密条令,我什么也不说这是最好的——但见你这么热情,一句话不说也不好。”Asm.Def停下手中的快速数论变换,“确实是树。”

    “然后你怎么算出来目标的位置?”

    “都需要按照基本算法,按照图论的那一套理论,去产生。听说过LCA吗?不是那个印度飞机,我是说最近公共祖先……”

    Asm.Def通过分析无线电信号得到了一棵有n个节点,以1为根的树。除1之外,节点i的父亲是p_i。节点带有权值,节点i的权值是w_i。

    我们定义某点的祖先为从根到它路径上的所有点(包括它本身),而两个节点a、b的最近公共祖先是某个点p,使得p同时是a、b的祖先,而且p离根最远。

    Asm.Def想要求出

    (文字:∑∑w_i*w_j*w_LCA(i,j)),

    其中LCA(i,j)是i、j的最近公共祖先,他认为这个值至关重要。由于这个值可能很大,Asm.Def只需要知道它模1,000,000,007(即10^9+7)的结果。

    【输入格式】

    第1行两个整数:n和w_1.

    第2行到第n行,第i行有两个整数p_i和w_i。

    【输出格式】

    一行一个整数,即答案模1,000,000,007的值。

    【样例输入】

    2 2
    1 1

    【样例输出】

    17

    【提示】

    1×1×1+1×2×2+2×1×2+2×2×2=17。

    对于30%的数据,n<=100,w_i<=10。

    对于60%的数据,n<=1000,w_i<=1000.

    对于100%的数据,1<=n<=10^5,0<=w_i<=10^9,1<=p_i<i.

     【超时code】

    dalao说没事先打暴力,说不定会想出思路,然而并没有。超时4个点。

    用define定义的mod一直错 输出1e009...

    然后建边时没有建双边....

    树剖写错.....

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    //#define mod 1e9
    const int mod=1e9+7;
    int w[100008],dad[100008],size[100008],top[100008],deep[100008];
    long long ans;
    int n,da;
    vector<int>vec[100008];
    void dfs1(int x) {
        size[x]=1;
        deep[x]=deep[dad[x]]+1;
        for(int i=0; i<vec[x].size(); i++) {
            if(dad[x]!=vec[x][i]) {
                dad[vec[x][i]]=x;
                dfs1(vec[x][i]);
                size[x]+=size[vec[x][i]];
            }
        }
    }
    void dfs2(int x) {
        if(!top[x])top[x]=x;
        int t=0;
        for(int i=0; i<vec[x].size(); i++) {
            if(dad[x]!=vec[x][i]&&size[vec[x][i]]>size[t])
                t=vec[x][i];
        }
        if(t) {
    //    top[t]=x;
            top[t]=top[x];
            dfs2(t);
        }
        for(int i=0; i<vec[x].size(); i++) {
            if(dad[x]!=vec[x][i]&&vec[x][i]!=t)
                dfs2(vec[x][i]);
        }
    }
    int lca(int x,int y) {
        for(; top[x]!=top[y];) {
            if(deep[x]<deep[y])
                swap(x,y);
    //    top[x]=dad[top[x]];
            x=dad[top[x]];
        }
        if(deep[x]<deep[y])return x;
        return y;
    }
    int main() {
        freopen("asm_algo.in","r",stdin);
        freopen("asm_algo.out","w",stdout);
        scanf("%d%d",&n,&w[1]);
        for(int i=2; i<=n; i++) {
            scanf("%d%d",&da,&w[i]);
            vec[da].push_back(i);
            vec[i].push_back(da);//建双向边
        }
        dfs1(1);
        dfs2(1);
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                ans=(ans+w[i]*w[j]*w[lca(i,j)])%mod;
        cout<<ans<<endl;
        return 0;
    }

    【AC code】

    一气之下全改成long long 就过了。

    【思路】

    如图的矩阵表示i,j的lca。发现对角线两侧是对称的(因为i,j的lca==j,i的lca);

    那么我们只要求出对角线的一侧的值再*2+对角线上的值就是答案。

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int mod=1e9+7;
    const int maxx=1e5;
    struct Edge
    {
        long long  x,y,next;
        Edge(int x=0,int y=0,int next=0):
            x(x),y(y),next(next){}
    }edge[maxx<<1];
    long long  head[maxx+1],w[maxx+1],sum[maxx+1],dad[maxx+1];
    long long n,sumedge,da;
    long long ans;
    void add(int x,int y)
    {
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    void dfs(int x)
    {
        sum[x]=w[x];
        for(long long  i=head[x];i;i=edge[i].next)
        {
            if(!dad[edge[i].y])
            {
                dad[edge[i].y]=x;dfs(edge[i].y);
                ans=(ans%mod+sum[x]%mod*sum[edge[i].y]%mod*w[x]%mod)%mod;
                sum[x]=(sum[x]%mod+sum[edge[i].y]%mod)%mod;
            }
        }
    }
    int main()
    {
        freopen("asm_algo.in","r",stdin);
        freopen("asm_algo.out","w",stdout);
        scanf("%lld%lld",&n,&w[1]);
        for(long long i=2;i<=n;i++)
        {
            scanf("%d%d",&da,w+i);//not &w+i;
            add(da,i);
        }
        dfs(1);
        ans=ans*2%mod;
        for(long long i=1;i<=n;i++)
        ans=(ans%mod+w[i]%mod*w[i]%mod*w[i]%mod)%mod;
        printf("%lld
    ",ans%mod);
        return 0;
    }
  • 相关阅读:
    CSP-S 代码基本框架
    Gradle build finished with 100 error(s) in 14s 629ms
    opencv2.3. 9+vs2012
    ButterKnife-- ButterKnife.bind(this); @BindView(R.id.bottomSelectView) BottomSelectView bottomSelectView;
    递归实现数组求和
    data structure begin!!
    递归实现全排列算法-161029
    简单粗暴-文件拓展名+任务管理器
    try to write a server
    在TextView中实时显示数据
  • 原文地址:https://www.cnblogs.com/zzyh/p/6937460.html
Copyright © 2011-2022 走看看