zoukankan      html  css  js  c++  java
  • [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

    这个题目应该不难想到,一个强连通分量内的所有蘑菇都可以采光(重复走,一直绕圈把路上的所有蘑菇采掉)

    那么一个强连通分量内的所有蘑菇数量是多少呢?

    ({n(n+1)<=w}) 的最大的 ({n}) ,解二次不等式,(n) 就是 (1.0*sqrt{0.25+2a}-0.5)

    然后价值就是 (nw−sum^{n}_{i=1}i(i+1)/2+w) ,也就是 ({nw−n(n+1)(n+2)/6+w})

    所以我们可以先用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
    ",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
    ",dfs(color[s]));
    	return 0;
    
    转载请注明出处--Xx_queue
  • 相关阅读:
    231. Power of Two
    204. Count Primes
    205. Isomorphic Strings
    203. Remove Linked List Elements
    179. Largest Number
    922. Sort Array By Parity II
    350. Intersection of Two Arrays II
    242. Valid Anagram
    164. Maximum Gap
    147. Insertion Sort List
  • 原文地址:https://www.cnblogs.com/Xx-queue/p/11708539.html
Copyright © 2011-2022 走看看