• 传球接力


    这里写图片描述
    这里写图片描述
    50%的做法:枚举每一个点,一直走到尽头,记录长度,更新答案。

    像这样的有n条边,n个点,每个点都有一条出边的点一定存在环。这样的图叫做 环加外向树

    这里写图片描述

    那么对于这道题的满分做法,先求出每颗树的叶子到树根的最长路径记为f[i],再找出环,然后每次枚举环上的点x,(环的长度len),用len-d[x]+f[to[x]]来更新答案就可以了。
    求环的时候,有很多种方法,然而用dfs是超时的。
    我们可以先求f数组,在求f数组的时候,先找出入度为零的点,更新它的邻接点的f,然后将这个点删去(将它邻接点的入度减 1)就可以了。这样我们在找环的时候,入度>0的点就是在环中的点。这样是一个较优的做法。

    先贴上50分代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #define LL long long
    #define M 500009
    using namespace std;
    int n,to[M],d[M];
    LL len;
    bool f[M];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&to[i],&d[i]);
        for(int i=1;i<=n;i++)
        {
            memset(f,0,sizeof(f));
            int x=i;LL l=0;
            while(to[x]&&!f[to[x]]&&d[x]>=0)
            {
                l+=d[x];
                f[x]=1;
                x=to[x];    
            }
            len=max(len,l); 
        }
        printf("%lld",len);
        return 0;
    }

    60分的dfs找环代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define LL long long
    #define M 500009
    using namespace std;
    int n,d[M],to[M],f[M],st[M],top,pos[M];
    int color[M],color_num;
    int from[M];
    vector <int> A[M]; 
    LL ans,len[M];
    bool vis[M];
    void dfs(int x)
    {
        vis[x]=1;st[++top]=x,pos[x]=top;
    
        if(color[to[x]]) return;
        if(!vis[to[x]]) vis[to[x]]=1,dfs(to[x]);
        else{
            ++color_num;
            for(int i=pos[to[x]];i<=top;i++) 
            {
                color[st[i]]=color_num;
                A[color_num].push_back(st[i]);
                len[color_num]+=d[st[i]];
            }
        }   
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {   
            scanf("%d%d",&to[i],&d[i]);
            from[to[i]]++;
        }
        for(int i=1;i<=n;i++)
        {
            if(!from[i]&&!vis[i])
            {
                memset(vis,0,sizeof(vis));
                dfs(i);
            }   
        }
        for(int i=1;i<=n;i++)
        {
            if(!from[i])
            {
                int x=i;
                while(1)
                {
                    f[to[x]]=max(f[to[x]],f[x]+d[x]);
                    if(color[to[x]]) break;
                    x=to[x]; 
                }
            } 
        }
    
        for(int i=1;i<=color_num;i++)
        {
            for(int j=0;j<A[i].size();j++)
            {
                ans=max(ans,f[to[A[i][j]]]+len[i]-d[A[i][j]]);
            }
        }
        printf("%lld",ans);
        return 0;
    }

    100分代码

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #define LL long long
    #define M 500009
    using namespace std;
    int n,d[M],to[M],f[M],from[M],q[M],L,R;
    LL ans,len;
    bool vis[M];
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {   
            scanf("%d%d",&to[i],&d[i]);
            from[to[i]]++;
        }
        for(int i=1;i<=n;i++)
        if(from[i]==0) q[++R]=i;
    
        while(L<R)
        {
            int x=q[++L];
            f[to[x]]=max(f[to[x]],f[x]+d[x]);
            if(--from[to[x]]==0) q[++R]=to[x];
        }
    
        for(int i=1;i<=n;i++)
        {
            if(!vis[i]&&from[i]>0)
            {
                int x=i;
                R=0;
                len=0;
                while(1)
                {
                    len+=d[x];
                    vis[x]=1;
                    q[++R]=x;
                    x=to[x];
                    if(x==i) break; 
                }
                for(int j=1;j<=R;j++)
                {
                    LL l=len-d[q[j]]+f[to[q[j]]];
                    ans=max(l,ans);
                }
            }
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    python远程执行dos命令
    python调用cmd显示中文乱码及调用cmd命令
    centos密码策略
    windows密码策略
    windows注册表解析说明
    Acwing-252-树(点分治)
    Gym-10071A-Queries(树状数组)
    2019ICPC沈阳网络赛-B-Dudu's maze(缩点)
    2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)
    平衡树
  • 原文地址:https://www.cnblogs.com/dfsac/p/7587809.html
Copyright © 2020-2023  润新知