zoukankan      html  css  js  c++  java
  • CodeForces

    题意:一张有向图,每条边上都有wi个蘑菇,第i次经过这条边能够采到w-(i-1)*i/2个蘑菇,直到它为0。问最多能在这张图上采多少个蘑菇。

    分析:在一个强连通分量内,边可以无限次地走直到该连通块内蘑菇被采完为止,因此每个强连通分量内的结果是确定的。

    设一条边权值为w,最大走过次数为t,解一元二次方程得 t = (int)(1+sqrt(1+8w));则该边对所在连通块的贡献为w*t - (t-1)*t*(t+1)/6。

    而不在任何一个强连通分量内的边,最多只能走一次。所以在缩点后的DAG上进行dp即可。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn =1e6+5;
    struct Edge{
        int v,next;
        LL val;  
    }edges[maxn],E[maxn];
    int head[maxn],tot,H[maxn],tt;
    stack<int> S;
    int pre[maxn],low[maxn],sccno[maxn],dfn,scc_cnt;
    LL W[maxn];
    LL dp[maxn];
    void init()
    {
        tot = dfn = scc_cnt=tt=0;
        memset(H,-1,sizeof(H));
        memset(W,0,sizeof(W));
        memset(dp,0,sizeof(dp));
        memset(pre,0,sizeof(pre));
        memset(sccno,0,sizeof(sccno));
        memset(head,-1,sizeof(head));
    }
    
    void AddEdge(int u,int v,LL val)   {
        edges[tot] = (Edge){v,head[u],val};
        head[u] = tot++;
    }
    
    void Tarjan(int u)
    {
        int v;
        pre[u]=low[u]=++dfn;
        S.push(u);
        for(int i=head[u];~i;i=edges[i].next){
            v= edges[i].v;
            if(!pre[v]){
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!sccno[v]){
                low[u]=min(low[u],pre[v]);
            }
        }
        if(pre[u]==low[u]){
            int x;
            ++scc_cnt;
            for(;;){
                x = S.top();S.pop();
                sccno[x]=scc_cnt;
                if(x==u)break;
            }
        }    
    }
    
    
    void nAddEdge(int u,int v,LL w)
    {
        E[tt] = (Edge){v,H[u],w};
        H[u] = tt++;
    }
    
    LL dfs(int u)
    {
        if(dp[u]) return dp[u];
        for(int i=H[u];~i;i=E[i].next){
            int v = E[i].v;
            dp[u] = max(dp[u],dfs(v)+E[i].val);
        }
        dp[u]+=W[u];
        return dp[u];
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        int N,M; 
        while(scanf("%d%d",&N,&M)==2){
            init();
            int st,u,v; LL w;
            while(M--){
                scanf("%d%d%lld",&u,&v,&w);
                AddEdge(u,v,w);
            }
            scanf("%d",&st);
            for(int i=1;i<=N;++i){
                if(!pre[i]){
                    Tarjan(i);
                }
            }
            
            for(int u =1;u<=N;++u){
                for(int i =head[u];~i;i = edges[i].next){
                    v = edges[i].v;
                    LL w = edges[i].val;
                    if(sccno[u]!=sccno[v]){
                        nAddEdge(sccno[u],sccno[v],w);
                    }
                    else{
                        int t = (int)(1+sqrt(1+8*w))/2;
                        W[sccno[u]] += (LL)t*w - (LL)(t-1)*t*(t+1)/6;
                    }
                }
            }
            for(int i=1;i<=scc_cnt;++i){
                if(!dp[i]){
                    dfs(i);
                }
            }
            printf("%lld
    ",dp[sccno[st]]);
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    电子商务网站的设计与实现(四):项目名称malling和一期开发计划
    电子商务网站的设计与实现(三):四大子系统,登录-账务-前端-后端
    电子商务网站的设计与实现(三):四大子系统,登录-账务-前端-后端
    删除垃圾软件,系统和网络出现故障
    删除垃圾软件,系统和网络出现故障
    2014年工作中遇到的20个问题:201-220
    2014年工作中遇到的20个问题:201-220
    电子商务网站的设计与实现(二):一期功能清单
    电子商务网站的设计与实现(二):一期功能清单
    CDS view注解解析
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9494938.html
Copyright © 2011-2022 走看看