• 洛谷P4742 [Wind Festival]Running In The Sky(Tarjan强联通缩点+记忆化搜索)


    题目链接:https://www.luogu.com.cn/problem/P4742

    思路:这个其实还是很简单的吧,为什么我会单独拿出来写一个博客呢?是因为这里的记忆化搜索在日后会对我有所启发吧。整体思路很简单:就是Tarjan强联通缩点后重建新图。然后在新图上跑dfs记忆化搜索。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,n) for(int i=a;i<=n;i++)
    #define per(i,n,a) for(int i=n;i>=a;i--)
    #define endl '
    '
    #define eps 0.000000001
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define IO ios::sync_with_stdio(false);cin.tie(0);
    using namespace std;
    const int INF=0x3f3f3f3f;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    const int mod=1e9+7;
    const int maxn=5e5+5;
    int tot,head[maxn];
    struct E{
        int to,next;
    }edge[maxn<<1];
    void add(int u,int v){
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    int n,m,p[maxn];
    int uu[maxn],vv[maxn];
    int low[maxn],vis[maxn],dfn[maxn],id[maxn],Max[maxn],sum[maxn],tott,cnt;
    stack<int> s;
    void tarjan(int x){
        dfn[x]=low[x]=++tott;
        s.push(x);vis[x]=1;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v]){
                low[x]=min(low[x],dfn[v]);
            }
        }
        if(low[x]==dfn[x]){
            ++cnt;
            while(1){
                int now=s.top();s.pop();
                id[now]=cnt;
                Max[cnt]=max(Max[cnt],p[now]);
                sum[cnt]+=p[now];
                vis[now]=0;
                if(x==now) break;
            }
        }
    }
    int ans1,ans2;
    int f[maxn],ff[maxn];
    void dfs(int x){
        if(f[x]) return ;
        f[x]=sum[x];
        ff[x]=Max[x];
        int M1=0,M2=0;
        for(int i=head[x];i!=-1;i=edge[i].next){
            int v=edge[i].to;
            dfs(v);
            if(f[v]>M1) M1=f[v],M2=ff[v];
            else if(f[v]==M1){
                if(ff[v]>M2) M2=ff[v]; 
            }
        }
        f[x]=f[x]+M1;
        ff[x]=max(ff[x],M2);
    }
    int main(){
        scanf("%d%d",&n,&m);mem(head,-1);tott=cnt=0;
        ans1=ans2=0;
        rep(i,1,n) scanf("%d",&p[i]);
        rep(i,1,m){
            scanf("%d%d",&uu[i],&vv[i]);
            add(uu[i],vv[i]);
        }
        rep(i,1,n){
            if(!dfn[i]) tarjan(i);
        }
        mem(head,-1);tot=0;
        rep(i,1,m){
            if(id[uu[i]]==id[vv[i]]) continue;
            add(id[uu[i]],id[vv[i]]);
        }
        rep(i,1,cnt){
            if(!f[i]){
                dfs(i);
            }
            if(f[i]>ans1) ans1=f[i],ans2=ff[i];
        }
        printf("%d %d
    ",ans1,ans2);
    }
    View Code
  • 相关阅读:
    下载flash我的三种方法
    随机变换背景图象(一个可以刷新心情的特效)
    禁止缓存
    [模板]字符串算法
    [学习笔记]有上下界的网络流
    [bzoj2809][Apio2012]dispatching
    [四校联考]Easy Problems
    [学习笔记]tarjan
    [vijos1780][NOIP2012]开车旅行
    记第一次打女队
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13289467.html
Copyright © 2020-2023  润新知