[2019 CSP-S赛前集训] [CF894E] Ralph and Mushrooms
题目链接:https://www.luogu.org/problem/CF894E
题目大意
Ralph打算去蘑菇森林采蘑菇。
蘑菇森林里有n个蘑菇丛,有m条有向的路连接这些丛林(可能连向自己,也可能两个丛林之间有多条路)。经过某条路时,Ralph可以采走这条路上的全部蘑菇。然而,这是一片神奇的蘑菇森林,蘑菇被采走后会重新长出来一些。但是,第k次走过这条路后,这条路上重新长出的蘑菇会比上次少k。(举个栗子,第一次有w个蘑菇,第二次有w-1个蘑菇,第三次有w-1-2个蘑菇,以此类推……)(还有,蘑菇的数量大于0)。
那么,Ralph最多可以采到多少蘑菇呢?
输入输出样例
输入 #1
2 2
1 2 4
2 1 4
1
输出 #1
16
输入 #2
3 3
1 2 4
2 3 3
1 3 8
1
输出 #2
8
这个题目应该不难想到,一个强连通分量内的所有蘑菇都可以采光(重复走,一直绕圈把路上的所有蘑菇采掉)
那么一个强连通分量内的所有蘑菇数量是多少呢?
的最大的 ,解二次不等式, 就是
然后价值就是 ,也就是
所以我们可以先用Tarjan缩点求出强连通分量,把边权合并到点上,重新建图,再来搜索一下就OK了;
那么注意几个地方:1.要开long long;
2.点权与边权混合加时不要漏加了终点的点权;
3.代码可能有点难调,耐心一点,一定可以调出来的(祭本题提交9次);
附上双倍经验:P2656 采蘑菇,稍微修改一下就能过了!
#include <bits/stdc++.h>
#define N (2000000+5)
#define int long long
using namespace std;
int n,m,s;
int top,sum,deep;
int dfn[N],low[N],color[N],vis[N],st[N];
int cnt[N],in[N],wp[N],f[N];
int u[N],v[N],wei[N];
vector <int> edge[N],w[N];
void Tarjan(int u)
{
vis[u]=1;
dfn[u]=low[u]=++deep;
st[++top]=u;
for(int i=0;i<edge[u].size();i++)
{
int now=edge[u][i];
if(!dfn[now])
{
Tarjan(now);
low[u]=min(low[u],low[now]);
}
else
{
if(vis[now]) low[u]=min(low[u],low[now]);
}
}
if(dfn[u]==low[u])
{
color[u]=++sum;
vis[u]=0;
while(st[top]!=u)
{
color[st[top]]=sum;
vis[st[top--]]=0;
}
top--;
}
}
int dfs(int u)
{
if(vis[u]) return f[u];
int res=0;
vis[u]=1;
for (int i=0;i<edge[u].size();i++)
{
int now=edge[u][i];
res=max(res,dfs(now)+w[u][i]);
}
return f[u]=res+wp[u];
}
int cont(int a)
{
int k=1.0*sqrt(0.25+2*a)-0.5;
return a*k-k*(k+1)*(k+2)/6+a;
}
signed main()
{
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&u[i],&v[i],&wei[i]);
edge[u[i]].push_back(v[i]);
}
for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
for(int i=1;i<=n;i++) vector<int>().swap(edge[i]);
for(int i=1;i<=m;i++)
{
if(color[u[i]]==color[v[i]])
{
wp[color[u[i]]]+=cont(wei[i]);
}
else
{
//printf("u=%lld v=%lld\n",color[u[i]],color[v[i]]);
edge[color[u[i]]].push_back(color[v[i]]);
w[color[u[i]]].push_back(wei[i]);
in[color[v[i]]]++;
}
}
scanf("%lld",&s);
memset(vis,0,sizeof(vis));
printf("%lld\n",dfs(color[s]));
return 0;
转载请注明出处--Xx_queue
分类:
图论系列
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· C# 13 中的新增功能实操
· Ollama本地部署大模型总结
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(4)
· langchain0.3教程:从0到1打造一个智能聊天机器人
· 用一种新的分类方法梳理设计模式的脉络