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
  • 相关阅读:
    SQLite-SQLiteDatabase 数据库实例练习
    全局配置一个ajax的错误监控
    文件上传&&验证文件格式
    CSS3 resize 属性
    select change()
    window.location.Reload()和window.location.href 区别
    条件检索
    jQuery $.ajax传递数组的traditional参数传递必须true 对象的序列化
    jquery中attr方法和prop方法的区别
    resize
  • 原文地址:https://www.cnblogs.com/Xx-queue/p/11708539.html
Copyright © 2011-2022 走看看