zoukankan      html  css  js  c++  java
  • [Luogu P3119] [USACO15JAN]草鉴定Grass Cownoisseur (缩点+图上DP)

    题面

    传送门:https://www.luogu.org/problemnew/show/P3119


    Solution

    这题显然要先把缩点做了。

    然后我们就可以考虑如何处理走反向边的问题。

    像我这样的蒟蒻,当然是使用搜索,带记忆化的那种(滑稽)。

    考虑设f(i,j)表示到达第i个点,还能走j次反向边,所能到达的最多的点的数量。

    转移可以表示为:

    如果x能到达1所在的强连通分量或max出来的值不为0,说明当前状态可行,否则不可行。

    然后用记忆化搜索表达出来就OK了


    Code

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<cstring>
    using namespace std;
    long long read()
    {
        long long x=0,f=1; char c=getchar();
        while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    const int N=100000+100;
    struct road
    {
        int to,IsBack;
        road (int A,int B)
        {
            to=A,IsBack=B;
        }
    };
    vector <int> e[N];
    vector <road> e2[N];
    int belong[N],nd_tot,nd_to,low[N],dfn[N],InStack[N],cnt[N];
    stack <int> st;
    void Tarjan(int now)
    {
        low[now]=dfn[now]=++nd_to;
        InStack[now]=true;
        st.push(now);
        for(int i=0;i<int(e[now].size());i++)
            if(dfn[e[now][i]]==0)
            {
                Tarjan(e[now][i]);
                low[now]=min(low[now],low[e[now][i]]);
            }
            else if(InStack[e[now][i]]==true)
                low[now]=min(low[now],low[e[now][i]]);
        if(low[now]==dfn[now])
        {
            nd_tot++;
            while(st.empty()==false)
            {
                int temp=st.top();
                st.pop();
                belong[temp]=nd_tot;
                InStack[temp]=false;
                cnt[nd_tot]++;
                if(temp==now)
                    break;
            }
        }
    }
    int n,m,S,f[N][2];
    int dfs(int now,int back)
    {
        if(f[now][back]>=0) return f[now][back];
        int t_ans=0;
        bool OK=false;
        for(int i=0;i<int(e2[now].size());i++)
            if(e2[now][i].to!=S and back-e2[now][i].IsBack>=0)
                t_ans=max(t_ans,dfs(e2[now][i].to,back-e2[now][i].IsBack));
            else if(back>=e2[now][i].IsBack)
                OK=true;
        if(t_ans!=0 or OK==true)
            return f[now][back]=t_ans+cnt[now];
        else
            return f[now][back]=0;
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            e[i].reserve(4),
            e2[i].reserve(4);
        for(int i=1;i<=m;i++)
        {
            int s=read(),t=read();
            e[s].push_back(t);
        }
        
        for(int i=1;i<=n;i++)
            if(dfn[i]==0)
                Tarjan(i);
        S=belong[1];
        for(int i=1;i<=n;i++)
            for(int j=0;j<int(e[i].size());j++)
                if(belong[i]!=belong[e[i][j]])
                {
                    e2[belong[i]].push_back(road(belong[e[i][j]],0));
                    e2[belong[e[i][j]]].push_back(road(belong[i],1));
                }
        
        memset(f,0x80,sizeof f);
        int ans=0;
        for(int i=0;i<int(e2[S].size());i++)
            ans=max(ans,dfs(e2[S][i].to,1-e2[S][i].IsBack));
        
        printf("%d",ans+cnt[S]);
        return 0;
    }
    C++(正解)
    自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
  • 相关阅读:
    “大型售票系统”和“真正的电商系统”在“库存”巨大的差异计算
    c#有关udp可靠传输(包传输数据包) 升级
    CreateCompatibleDC工作原理
    Android 内存管理 &amp;Memory Leak &amp; OOM 分析
    ubuntu文本界面乱码的中国解决方案
    hdu 4972 A simple dynamic programming problem(高效)
    java定义和实现接口
    HTTP 404
    pcre函数具体解释
    Android项目开发五-《星星生活志》1.使用MediaRecorder录制音频
  • 原文地址:https://www.cnblogs.com/GoldenPotato/p/9168356.html
Copyright © 2011-2022 走看看