[トレーニング前2019CSP-S] [CF894E]ラルフとキノコ

トピックへのリンク: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;

おすすめ

転載: www.cnblogs.com/Xx-queue/p/11708539.html