采蘑菇

洛咕

题意:ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次,可以采走这条路上所有的蘑菇.由于ESQMS森林是一片神奇的沃土,所以一条路上的蘑菇被采过后,又会长出一些新的蘑菇,数量为原来蘑菇的数量乘上这条路的“恢复系数”,向下取整.比如,一条路上有4个蘑菇,这条路的“恢复系数”为0.7,则第一~四次经过这条路径所能采到的蘑菇数量分别为4,2,1,0.现在,小胖和ZYR从S号小树丛出发,求他们最多能采到多少蘑菇.

分析:根据题意,只有强连通分量里面的边才能够采完所有蘑菇,其它的边只能采第一次的蘑菇数量.所以跑个有向图的\(Tarjan\)缩点.重新建图的时候,枚举每条边\((u->v)\),如果\(u,v\)不属于同一个强连通分量就直接加入新的图中,否则计算这条边会对这个强连通分量产生多少蘑菇贡献.

建图后直接从起点开始跑 既有边权又有点权 的最长路就好了.初始化的时候记得把起点的点权加进去.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=100005;
const int M=200005;
int n,m,S,ans,dis[N],a[M],b[M],c[M],size[N],in[N];
int tim,top,num,dfn[N],low[N],st[N],color[N];
int tot,head[N],nxt[M],to[M],w[M];
double d[M],ww[M];queue<int>q;
inline void add(int a,int b,int c,double d){
    nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;w[tot]=c;ww[tot]=d;
}
inline void Add(int a,int b,int c){
    nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;w[tot]=c;
}
inline void tarjan(int u){
    dfn[u]=low[u]=++tim;st[++top]=u;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!color[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        color[u]=++num;
        while(st[top]!=u){
            color[st[top]]=num;
            --top;
        }
        --top;
    }
}
inline int calc(int s,int hf){
    int sum=0;
    while(s){
        sum+=s;
        s=(int)s*hf;
    }
    return sum;
}
int main(){
    n=read();m=read();
    for(int i=1;i<=m;++i){
        a[i]=read();b[i]=read();c[i]=read();cin>>d[i];
        add(a[i],b[i],c[i],d[i]);
    }
    S=read();
    for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
    tot=0;memset(head,0,sizeof(head));
    for(int i=1;i<=m;++i){
        if(color[a[i]]!=color[b[i]])
            Add(color[a[i]],color[b[i]],w[i]);
        else{//如果这条边在强连通分量里面就计算贡献
            int s=w[i];
            while(s){
                size[color[a[i]]]+=s;
                s=(int)s*ww[i];
            }
        }
    }
    memset(dis,-1,sizeof(dis));
    q.push(color[S]);dis[color[S]]=size[color[S]];//初始化
    while(q.size()){
        int u=q.front();q.pop();in[u]=0;
        for(int i=head[u];i;i=nxt[i]){
            int v=to[i];
            if(dis[v]<dis[u]+w[i]+size[v]){//最长路
                dis[v]=dis[u]+w[i]+size[v];
                if(!in[v])in[v]=1,q.push(v);
            }
        }
    }
    for(int i=1;i<=num;++i)ans=max(ans,dis[i]);//找到最大值
    printf("%d\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/PPXppx/p/11579314.html

时间: 2024-08-09 00:55:52

采蘑菇的相关文章

洛谷2656 采蘑菇

本题地址:http://www.luogu.org/problem/show?pid=2656 题目描述 小胖和ZYR要去ESQMS森林采蘑菇.      ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次,可以采走这条路上所有的蘑菇.由于ESQMS森林是一片神奇的沃土,所以一条路上的蘑菇被采过后,又会长出一些新的蘑菇,数量为原来蘑菇的数量乘上这条路的“恢复系数”,再下取整.      比如,一条路上有4个蘑菇,这条路

[Luogu 2656] 采蘑菇

Description 小胖和ZYR要去ESQMS森林采蘑菇. ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇.小胖和ZYR经过某条小径一次,可以采走这条路上所有的蘑菇.由于ESQMS森林是一片神奇的沃土,所以一条路上的蘑菇被采过后,又会长出一些新的蘑菇,数量为原来蘑菇的数量乘上这条路的"恢复系数",再下取整. 比如,一条路上有4个蘑菇,这条路的"恢复系数"为0.7,则第一~四次经过这条路径所能采到的蘑菇数量分别为

【细节题 离线 树状数组】luoguP4919 Marisa采蘑菇

歧义差评:但是和题意理解一样了之后细节依然处理了很久,说明还是水平不够…… 题目描述 Marisa来到了森林之中,看到了一排nn个五颜六色的蘑菇,编号从1-n1−n,这些蘑菇的颜色分别为col[1],col[2]...col[n]col[1],col[2]...col[n]由于她很挑剔,所以她只会采那些"魔法蘑菇" 一个蘑菇被叫做"魔法蘑菇",当且仅当它在给定的某段区间内,并且在这段给定区间内与它颜色相同的蘑菇(包括它本身)的个数 与在这个给定区间外这种颜色的蘑菇的

Luogu P2656 采蘑菇

尽管是缩点的习题,思路也是在看了题解后才明白的. 首先,每个强连通分量内的点都是一定互通的,也就是可以完全把这里面的边都跑满,摘掉所有能摘的蘑菇.那么,考虑给每一个强连通分量化为的新点一个点权,代表摘光蘑菇能拿到的边权之和.然后,在新点之间保留原来的桥及其初始权值.(每一个桥一定只能跑一遍,否则说明这两个本应单向通行的分量之间有返回的路径,则二者可构成一个更大的分量.这个结论正是tarjan算法求有向图dcc的核心原理.)现在得到了一张新图,问题在于如何在一张包含点权.边权的DAG上求起始于定点

[Luogu2656]采蘑菇

题目大意: 给你一个有向图,每条边有一个边权w以及恢复系数k, 你从s点出发乱走,经过某条边时会获得相应的收益w,而当第二次经过这条边时相应的收益为w*k下取整. 问你最大能获得的收益为多少? 思路: 缩点+DP. 首先跑一下Tarjan(只要从s开始跑,因为没跑到的地方肯定和答案没关系). 对于每个强连通分量,我们算一下经过这个强联通分量能获得的总收益sum(就是拼命在这上面绕圈圈). 把原图缩为一个DAG,然后就可以DP了. 设当前点为i,后继结点为j,边权为w,j的SCC的总收益为sum[

4.3 省选模拟赛 采蘑菇 点分治

给出一棵树 每个点都有一个颜色ci 问 从i号点出发到任意一个点的路径上本质不同的颜色之和. \(n\leq 300000\) 光线性扫描时不行的 显然有\(n^2\)的暴力. 考虑树是一条链的时候怎么做? 可以发现先求出1的答案然后维护换根的过程 记录每个点颜色的pre 前驱 nex后继很容易通过分类讨论得到答案. 考虑树的时候怎么做?还是维护换根的过程 当两个点颜色相同的时候 答案显然一样,当不同的时候 可以分析得出 要查自己子树内没有自己父亲颜色的祖先的节点个数.还要查 自己子树之外没有自

模仿东京首页banner轮播,京东新闻上下滚动动画实现(动画实现)

接着上篇 微信小程序-阅读小程序demo写:http://www.cnblogs.com/muyixiaoguang/p/5917986.html 首页banner动画实现 京东新闻上下动画实现 想着模仿京东首页呢,结果也没赶得及写完,轮播图让我搞了好长时间.也好,那就国庆8天好好的写一下,这里写了一半,先放着.先介绍一下这一半的内容.       还是老规矩,先放个图吧,虽然才一点点了 上线的banner大图和京东头条都是可以滚动的,抄写微信小程序社区官方qq群:390289365里 Nige

养养鱼,种种花,做做菜,生活是很好玩儿的

一直以为汪曾祺最近几年才去世,上网查了一下,才知道这个老头儿97年就已经不在了. 最早读到他的小说是<受戒>,被无忧无虑的江南生活所吸引,觉得很美.其实是先生所构想的世界很美,现实中不存在这样的世界,也许以前存在过,后来又消失了.之后在一本很厚的散文集中读到<跑警报>,写得很有意思,来来回回度过很多遍.这本<百年百篇经典散文>封面画了两颗很大的松果,屡次搬家中无故遗失,我专门到旧书网上淘了一本回来,成为我的常读书之一. <跑警报>写昆明西南联大的生活,最要紧

100个精彩的开源游戏

街机游戏 1.Andy's Super Great Park 骑在过山车上,躲避障碍的同时收集气球.游戏有25关,另外还有18关需要得到高分才能解锁.支持的操作系统:Windows,Linux,Android. 2.Armagetron Advanced 这是Tron的3D克隆版.在游戏中,你需要控制你的光圈来使你的竞争对手比你早撞上墙.支持单人游戏和最多16人联网游戏.支持的操作系统Windows, Linux, OS X, Android. 3.BZFlag 全称是"Battle Zone