• codeforces 894E


    显然如果走到一个SCC里,那么可以把这个SCC里的权值反复走取完

    连接SCC之间的边显然只能走一次(缩点后是DAG)

    那么我们tarjan缩点,然后在DAG上DP,就是个带权最长路,随便DP一下就行了

    边权就是w,点权需要另外计算

    对每个SCC内部的边,假设边权为(w),那么下降次数是满足(frac{(t+1)*t}{2} leq w)的最大的(t),这个可以二分出来

    然后考虑贡献了多少,用整体减掉下降的每种权值的贡献,实际上是((t+1)*w-t*1-(t-1)*2-…-2*(t-1)-1*t)

    后面那部分写成和式的形式是(sum_{i=1}^{t}{i*(t+1-i)})

    然后这个拆开来可以转化成等差数列和加平方和计算

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define maxn 1000005
     4 using namespace std;
     5 int n,m,s;
     6 vector< pair<int,int> > g[maxn],g2[maxn];
     7 stack<int> stk;
     8 vector<int> scc[maxn];
     9 int pre[maxn],low[maxn],bel[maxn],Tim,cnt;
    10 void tarjan(int u)
    11 {
    12     pre[u]=low[u]=++Tim;
    13     stk.push(u);
    14     for(auto pa:g[u])
    15     {
    16         int v=pa.first;
    17         if(!pre[v])tarjan(v),low[u]=min(low[u],low[v]);
    18         else if(!bel[v])low[u]=min(low[u],pre[v]);
    19     }
    20     if(low[u]==pre[u])
    21     {
    22         cnt++;
    23         while(1)
    24         {
    25             int x=stk.top();stk.pop();
    26             bel[x]=cnt;
    27             scc[cnt].push_back(x);
    28             if(x==u)break;
    29         } 
    30     }
    31 }
    32 ll calc(ll w)
    33 {
    34     ll l=0,r=20000,t=0;
    35     while(l<=r)
    36     {
    37         ll mid=(l+r)>>1;
    38         if(mid*(mid+1)<=2*w)t=mid,l=mid+1;
    39         else r=mid-1;
    40     }
    41     return (t+1)*w-((t+1)*(t+1)*t/2-t*(t+1)*(2*t+1)/6);
    42 }
    43 ll we[maxn],dp[maxn];
    44 void dfs(int u)
    45 {
    46     if(dp[u])return;
    47     dp[u]=0;
    48     for(auto pa:g2[u])
    49     {
    50         int v=pa.first,w=pa.second;
    51         dfs(v);
    52         dp[u]=max(dp[u],dp[v]+w);
    53     }
    54     dp[u]+=we[u];
    55 }
    56 int main()
    57 {
    58     scanf("%d%d",&n,&m);
    59     for(int u,v,w,i=1;i<=m;++i)
    60     {
    61         scanf("%d%d%d",&u,&v,&w);
    62         g[u].push_back(make_pair(v,w));
    63     }
    64     Tim=cnt=0;
    65     for(int i=1;i<=n;++i)if(!pre[i])tarjan(i);
    66     for(int u=1;u<=n;++u)
    67     {
    68         for(auto pa:g[u])
    69         {
    70             int v=pa.first,w=pa.second;
    71             if(bel[u]==bel[v])we[bel[u]]+=calc(w);
    72             else g2[bel[u]].push_back(make_pair(bel[v],w));
    73         }
    74     }
    75     scanf("%d",&s);
    76     dfs(bel[s]);
    77     printf("%lld
    ",dp[bel[s]]);
    78 }
    View Code
  • 相关阅读:
    SQL SERVER2017 安装程序无法与下载服务器联系。无法安装机器学习服务的问题解决方式
    Kali Linux无法访问网络的问题
    Vue的冒泡事件
    记录阿里云ECS(Centos7.4)安装mysql 8.0.X服务
    沧桑巨变中焕发青春活力-记极1s HC5661A 打怪升级之路
    Asp.Net MVC过滤器小试牛刀
    C# Windows Service调用IBM Lotus Notes发送邮件
    记录一些js框架用途
    vc14(vs2015) 编译php7 记录
    C++ API方式连接mysql数据库实现增删改查
  • 原文地址:https://www.cnblogs.com/uuzlove/p/12294133.html
Copyright © 2020-2023  润新知