トピックへのリンク:https://www.luogu.org/problem/CF894E
効果の対象と
ラルフは、森のキノコをキノコになるだろう。
キノコフォレストキノコnの塊、及びmは(多分、それ自体に、2つのジャングルの間に複数の経路が存在し得る)、これらのジャングルを接続する方法を持たなければなりません。ルートを渡し、ラルフはすべてこの道を選んでキノコを行くことができます。しかし、これは番号をバック成長するままにされた魔法の森のキノコ、キノコ狩りです。k番目のは、この道を旅した後、しかし、この道は最後のk個未満のキノコを再成長します。(栗、Wキノコ初めて、第二の時間キノコW-1、W-1〜第3の時間キノコ、......など)も(、0より大きいキノコの数)。
まあ、ラルフはそれにどのように多くのキノコを拾いますか?
サンプル入力出力
入力#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
このトピックは強連結成分内のすべてのキノコは、光することができ、難しいことではありませんだと思う(行くために繰り返して、拾い出しキノコのすべての方法を一周されています)
そして、強連結成分内のすべてのキノコの数はどのくらいですか?
\({N(N + 1 )<= W} \) 最大\(N-} {\)は、第2の溶液不等式、\(\ N-)がある\(1.0 * \ SQRT {0.25 + 2A} -0.5 \)
その値は、(N ^ {} _ {I} NW-\ SUMを1 = I(Iは、+ 1)/ 2 + W \)\、すなわち\({NW-N(N + 1)(N + 2) / 6 + W} \)
だから我々は最初のTarjanポイント還元得た強連結成分を使用することができ、右側の合流点は、再構築されたマップ、OKに再度検索します。
だから、いくつかの場所に注意を払う:1、長い長いを開くには;.
2.右側と混合プラス点右端を添加したときに漏れない権利をタップ。
3.コードは、少し難しいが、我慢して、調整します(この質問は9を提出祭)を呼び出すようにしてくださいすることであってもよいです。
#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;