codeforces 894 E(scc + dp)

来源:互联网 发布:维金斯马刺数据 编辑:程序博客网 时间:2024/05/19 23:04

题目链接

E. Ralph and Mushrooms

分析

很显然如果在同一个连通分量内,它可以重复踩直到踩完.而重复踩,能踩到的蘑菇数可以预处理,然后二分求得.

那么我们将它求强连通再缩点后,问题就简单了,求出每个scc的权值作为节点权值,然后dp就行.

感觉本人代码有点搓,估计是很久没写过 scc缩点了,等会儿去看看大佬的姿势再更

AC code

#include <bits/stdc++.h>using namespace std;#define ms(x,v) (memset((x),(v),sizeof(x)))#define pb push_back#define mp make_pair#define fi first#define se second#define INF 0x3f3f3f3f#define INF64 0x3f3f3f3f3f3f3f3ftypedef long long LL;typedef pair<int,int > Pair;const int maxn = 1e6 +10;const int maxv = 1e8+10;const int MOD = 1e9+7;LL tmp[maxn],sum[maxn],t=0;inline LL weight(LL x){    int p = lower_bound(tmp,tmp+t,x) - tmp-1;    return x*(p+1) - sum[p];}int n,m,s;LL ans =0;bool vis[maxn];LL node[maxn],dp[maxn];//缩点后贡献//sccstd::vector<int> sc_node[maxn];std::vector<Pair> G[maxn];int dfn[maxn],low[maxn];int dfs_clock=0;int scc[maxn],scc_cnt=0;stack<int> S;//辅助栈void dfs(int u) {    low[u] = dfn[u] = ++dfs_clock;    S.push(u);    for(auto e:G[u]){         int v = e.fi;        if(!dfn[v]){            //未访问            dfs(v);            low[u] = min(low[v],low[u]);        }else if(!scc[v])low[u] = min(low[v],low[u]);    }    //计算出low值之后看是否满足起始条件    if(low[u] == dfn[u]){        //标记        scc_cnt++;        while (true) {            int v = S.top();S.pop();            scc[v] = scc_cnt;            if(v == u)break;        }    }}LL solve(int u) {    if(dp[u]!=-1)return dp[u];    dp[u] = node[u];    LL ans = 0;    for(auto v : sc_node[u]){        for(auto e : G[v])            if(scc[e.fi] != u){                ans = max(ans,solve(scc[e.fi])+e.se);            }    }    return dp[u]+=ans;}int main(int argc, char const *argv[]) {     for(t=0; tmp[t-1]<maxv ; ++t)tmp[t] = t+ tmp[t-1],sum[t]=tmp[t]+sum[t-1];     cin>>n>>m;     for(int i=0 ; i<m ; ++i){         int x,y,w;         scanf("%d%d%d",&x,&y,&w );         G[x].pb(mp(y,w));     }     cin>>s;     for(int i=1 ; i<=n ; ++i)        if(!dfn[i])dfs(i);     for(int i=1 ; i<=n ; ++i){         sc_node[scc[i]].pb(i);         for(auto e: G[i]){             if(scc[e.fi]==scc[i])node[scc[i]]+=weight(e.se);         }     }     ms(dp,-1);     std::cout << solve(scc[s]) << '\n';    return 0;}
原创粉丝点击