【题解】CF894E Ralph and Mushrooms (缩点)

【题解】CF894E Ralph and Mushrooms (缩点)

这是紫?给个解方程算法

考虑一条边若可以重复遍历说明一定有环,有环的话一定会把环上的蘑菇榨干,考虑一条边从全部到榨干的贡献是多少

\[\sum_{i=0}^x (w-\sum_{j=0}^i j)=\sum_{i=0}^x (w-{i(i+1)\over 2}) \]

那么考虑解出\(x\)的值,根据初中知识解出来\(x=\lfloor{-1+\sqrt{1+8w}\over 2}\rfloor\),预处理\(\sum {i(i+1)\over 2}\)可以直接计算贡献(其实也可以解通项公式)

然后Tarjan缩点之后变成DAG上的DP,同时有点权和边权的DAG DP

时间复杂度\(O(n)\)

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>

using namespace std;  typedef long long ll;   char __buf[1<<18],*__c=__buf,*__ed=__buf;
inline int qr(){
	register int ret=0,f=0;
	register char c=getchar();
	while(!isdigit(c))f|=c==45,c=getchar();
	while(isdigit(c)) ret=ret*10+c-48,c=getchar();
	return f?-ret:ret;
}

const int maxn=1e6+5;
struct E{int to,w;};
vector<E> e[maxn],e2[maxn];
inline void add(const int&fr,const int&to,const int&w){e[fr].push_back({to,w});}
inline void add2(const int&fr,const int&to,const int&w){
	e2[fr].push_back({to,w});
}
int n,m;
int qaq[maxn],cnt;
ll w[maxn],dp[maxn];
bool usd[maxn];
int low[maxn],dfn[maxn],in[maxn],stk[maxn],top,siz[maxn];
ll s[maxn];
 
void dfs(const int&now){
	stk[++top]=now; in[now]=1;
	low[now]=dfn[now]=++*dfn;
	for(auto t:e[now]){
		if(!dfn[t.to]) dfs(t.to),low[now]=min(low[now],low[t.to]);
		else if(in[t.to]) low[now]=min(dfn[t.to],low[now]);
	}
	if(low[now]==dfn[now]){
		++cnt;
		int temp;
		do temp=stk[top--],in[temp]=0,qaq[temp]=cnt,++siz[cnt];
		while(temp!=now);
	}
}

ll Dp(const int&now){
	if(usd[now]) return dp[now];
	dp[now]=0;
	for(auto t:e2[now]) dp[now]=max(dp[now],Dp(t.to)+t.w);
	usd[now]=1;
	return dp[now]=w[now]+dp[now];
}

int main(){
	n=qr(); m=qr();
	for(int t=1,t1,t2,t3;t<=m;++t) t1=qr(),t2=qr(),t3=qr(),add(t1,t2,t3);
	for(int t=1;t<maxn;++t) s[t]=s[t-1]+(1ll*t*(t+1)>>1);
	int S=qr();
	dfs(S);
	for(int t=1;t<=n;++t)
		for(auto i:e[t]){
			if(qaq[t]==qaq[i.to]) {
				int k=(sqrt((long double)1+8ll*i.w)-1)/2.0;
				w[qaq[t]]=w[qaq[t]]+(k+1ll)*i.w-s[k];
			}
			else add2(qaq[t],qaq[i.to],i.w);
		}
	ll ans=Dp(qaq[S]);
	printf("%lld\n",ans);
	return 0;
}



posted @ 2019-11-06 19:14  谁是鸽王  阅读(153)  评论(0编辑  收藏  举报