zoukankan      html  css  js  c++  java
  • 洛谷 P2656 采蘑菇 树形DP+缩点+坑点

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

    分析

      这其实是个一眼题(bushi

      发现如果没有那个恢复系数,缩个点就完了,有恢复系数呢?你发现这个恢复系数其实在DAG中没有用,因为走不回去不管怎么恢复都没啥用,所以对于走不回去的子图没有什么用,于是就想到了缩点,把每个强连通缩成一个点就完了,因为我能恢复的话肯定走的越多越好,所以就把每个强连通都榨干就完了,统计答案就dp一下,正好刚学的树形dp,所以大概思路就有了。

      我们先通过tarjan跑出强连通分量(有向图),然后缩点,最后dp,转移方程也挺简单的,dp[i]表示以i为跟的子树,初始化为W[i]

                    (dp[i]+=max(dp[v]))我最开始想的版本

      但是有一个问题,这么定义的话缩点前权值在边上,缩点后权值在点上,我起初的处理办法是将边权都压到边的终点,因为我只有走过这条边才能获得这个权值,乍一看是没啥问题,但是呢?的确如果从根开始dp不会有问题,但这道题是从某一不定的节点开始dp的,这样就会出问题。

      比如这里,我t->s这条边的权值会被压到s点上,如果我从t开始dp,没问题,从s开始,明明没有走那条边,却加上了边权,WA。

      解决这个问题很简单啊,就特判一下,同一个连通分量内的点把权值压在点上,另外的放在边上,dp方程改成

                     (dp[i]+=max(dp[v]+E.val))

      然后这个问题就解决了,这道题一开始Wa的主要原因还是点权边权的处理,当然也可能是没想太明白就开始打代码,导致出现问题,总结一下,以后要先想明白再写,想出来思路也不一定对

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int N=8e4+10,M=2e5+10;
    struct Edge{
       int fro,nxt,to,val;
       double hui;
    }e[M],E[M];
    int Head[N],len;
    void Ins(int a,int b,int c,double d){
       e[++len].fro=a;e[len].to=b;e[len].nxt=Head[a];
       Head[a]=len;e[len].val=c;e[len].hui=d;
    }
    inline int read(){
       char ch=getchar();
       while(ch<'0'||ch>'9')ch=getchar();
       int x=0;
       while(ch<='9'&&ch>='0'){
           x=x*10+ch-'0';
           ch=getchar();
       }
       return x;
    }
    int dfn[N],low[N],belong[N],stk[N],top,scc_cnt,num;
    void tarjan(int u){
       dfn[u]=low[u]=++num;
       stk[++top]=u;
       for(int i=Head[u];i;i=e[i].nxt){
           int v=e[i].to;
           if(!dfn[v]){
               tarjan(v);
               low[u]=min(low[u],low[v]);
           }else if(!belong[v])low[u]=min(low[u],dfn[v]);
       }
       if(low[u]==dfn[u]){
           scc_cnt++;
           while(1){
               int x=stk[top--];
               belong[x]=scc_cnt;
               if(x==u)break;
           }
       }
    }
    int H[N],l,w[N];
    void I(int a,int b,int c){
       E[++l].to=b;E[l].nxt=H[a];H[a]=l;E[l].val=c;
    }
    int dp[N];
    void dfs(int u){
       if(dp[u])return;
       dp[u]=w[u];
       int now=0;
       for(int x=H[u];x;x=E[x].nxt){
           int v=E[x].to;
           dfs(v);
           now=max(now,dp[v]+E[x].val);
       }
       dp[u]+=now;
    }
    int main(){
       int n,m;
       n=read();m=read();
       for(int i=1;i<=m;i++){
           int a,b,c;double d;
           a=read();b=read();c=read();cin>>d;
           Ins(a,b,c,d);
       }
       int s=read();
       tarjan(s);
       for(int i=1;i<=m;i++){
           int u=belong[e[i].fro],v=belong[e[i].to];
           if(u!=v)I(u,v,e[i].val);
           if(u==v){
               int now=e[i].val;double f=e[i].hui;
               while(now){
                   w[v]+=now;
                   now=(int)now*f;   
               }
           }
       }
       dfs(belong[s]);
       cout<<dp[belong[s]];
    }
    
  • 相关阅读:
    数组_leetcode283
    数组_leetcode438
    数组_leetcode215
    数组_leetcode167
    数组_leetcode209
    数组_leetcode88
    数组_leetcode80
    数组_leetcode76
    数组_leetcode75
    数组_leetcode27
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12630659.html
Copyright © 2011-2022 走看看