洛谷2656 采蘑菇

本题地址:http://www.luogu.org/problem/show?pid=2656

题目描述

小胖和ZYR要去ESQMS森林采蘑菇。
     ESQMS森林间有N个小树丛,M条小径,每条小径都是单向的,连接两个小树丛,上面都有一定数量的蘑菇。小胖和ZYR经过某条小径一次,可以采走这条路上所有的蘑菇。由于ESQMS森林是一片神奇的沃土,所以一条路上的蘑菇被采过后,又会长出一些新的蘑菇,数量为原来蘑菇的数量乘上这条路的“恢复系数”,再下取整。
     比如,一条路上有4个蘑菇,这条路的“恢复系数”为0.7,则第一~四次经过这条路径所能采到的蘑菇数量分别为4,2,1,0.
     现在,小胖和ZYR从S号小树丛出发,求他们最多能采到多少蘑菇。
     对于30%的数据,N<=7,M<=15
     另有30%的数据,满足所有“恢复系数”为0
     对于100%的数据,N<=80,000,M<=200,000,0.1<=恢复系数<=0.8且仅有一位小数,1<=S<=N.

输入输出格式

输入格式:

第一行,N和M
第2……M+1行,每行4个数字,分别表示一条小路的起点,终点,初始蘑菇数,恢复系数。
第M+2行,一个数字S

输出格式:

一个数字,表示最多能采到多少蘑菇,在int32范围内。

输入输出样例

输入样例#1:

3 3

1 2 4 0.5

1 3 7 0.1

2 3 4 0.6

1

输出样例#1:

8

【思路】

强连通分量+最长路。

Tarjan算法求SCC+缩点。SCC中的结点是可以互相到达的因此SCC内部的边权可以全部获得,将每条指向SCC的边权加上SCC的内部边权,再求一遍最长路即可。

需要注意的有:

1、  不要将w提前分解成边。

2、  不要把大数组开在函数里面,否则会RE =-=。这点学了。

【代码】

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<stack>
  5 #include<cmath>
  6 #include<iostream>
  7 using namespace std;
  8
  9 const int maxn = 80000+10,maxm=200000+10;
 10 const int INF=1<<30;
 11 struct Edge{
 12     int v,w,next;
 13     double f;
 14 }e[maxm];
 15 int en=-1,front[maxn];
 16
 17 int n,m,s;
 18
 19 stack<int> S;
 20 int scc_cnt,dfs_clock;
 21 int sccno[maxn],pre[maxn],lowlink[maxn],scc_v[maxn];
 22 void dfs(int u) {
 23     pre[u]=lowlink[u]=++dfs_clock;
 24     S.push(u);
 25     for(int i=front[u];i>=0;i=e[i].next){
 26         int v=e[i].v;
 27         if(!pre[v]) {
 28             dfs(v);
 29             lowlink[u]=min(lowlink[u],lowlink[v]);
 30         }
 31         else if(!sccno[v]) {
 32             lowlink[u]=min(lowlink[u],pre[v]);
 33         }
 34     }
 35     if(lowlink[u]==pre[u])
 36     {
 37        scc_cnt++;
 38        for(;;) {
 39            int v=S.top(); S.pop();
 40            sccno[v]=scc_cnt;
 41            if(v==u) break;
 42        }
 43     }
 44 }
 45 void find_scc(int n) {
 46     dfs_clock=scc_cnt=0;
 47     memset(pre,0,sizeof(pre));
 48     memset(sccno,0,sizeof(sccno));
 49     for(int i=1;i<=n;i++)
 50        if(!pre[i]) dfs(i);
 51 }
 52
 53
 54 inline void AddEdge(int u,int v,int w,double f) {
 55     en++; e[en].v=v; e[en].w=w; e[en].f=f; e[en].next=front[u]; front[u]=en;
 56 }
 57
 58 struct SPFA
 59 {
 60      Edge es[maxm];
 61      int esn,fr[maxn];
 62      int inq[maxn],d[maxn];
 63      queue<int> q;
 64      int n;
 65      void init(int n) {
 66             this->n=n; esn=0;
 67             memset(fr,-1,sizeof(fr));
 68      }
 69      void addedge(int u,int v,int w) {
 70             esn++; es[esn].v=v; es[esn].w=w; es[esn].next=fr[u]; fr[u]=esn;
 71      }
 72      void solve(int s) {
 73          memset(inq,0,sizeof(inq));
 74          for(int i=1;i<=n;i++) d[i]=-INF;
 75
 76          d[s]=scc_v[s]; inq[s]=1; q.push(s);
 77           while(!q.empty()) {
 78              int u=q.front(); q.pop(); inq[u]=0;
 79              for(int i=fr[u];i>=0;i=es[i].next) {
 80                  int v=es[i].v,w=es[i].w;
 81                  if(d[v]<d[u]+w) {
 82                      d[v]=d[u]+w;
 83                      if(!inq[v]) {
 84                          inq[v]=1;
 85                          q.push(v);
 86                      }
 87                  }
 88              }
 89         }
 90         int ans=0;
 91         for(int i=1;i<=n;i++) ans=max(ans,d[i]);
 92         printf("%d\n",ans);
 93     }
 94 };
 95 SPFA spfa;
 96
 97 int main() {
 98     memset(front,-1,sizeof(front));
 99     scanf("%d%d",&n,&m);
100     int u,v,w; double f;
101     for(int i=0;i<m;i++) {
102         scanf("%d%d%d%lf",&u,&v,&w,&f);
103         AddEdge(u,v,w,f);
104     }
105     scanf("%d",&s);
106     find_scc(n);
107
108     spfa.init(scc_cnt);
109
110     for(int u=1;u<=n;u++) {
111         for(int i=front[u];i>=0;i=e[i].next) {
112             int v=e[i].v,w=e[i].w;
113             double f=e[i].f;
114             if(sccno[u]==sccno[v])
115             {
116                 scc_v[sccno[v]] += w; w=(int)(w*f);
117                 while(w) {
118                     scc_v[sccno[v]] += w;
119                     w=(int)(w*f);
120                 }
121             }
122         }
123     }
124     for(int u=1;u<=n;u++) {
125         for(int i=front[u];i>=0;i=e[i].next) {
126             int v=e[i].v,w=e[i].w;
127             if(sccno[u]!=sccno[v]) {
128                 w += scc_v[sccno[v]];    //sccno[v]
129                 spfa.addedge(sccno[u],sccno[v],w);  //sccno[u]->sccno[v]
130             }
131         }
132     }
133
134     spfa.solve(sccno[s]);
135
136     return 0;
137 }
时间: 2024-08-09 00:55:41

洛谷2656 采蘑菇的相关文章

[Luogu 2656] 采蘑菇

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

洛谷P2056 采花

P2056 采花 52通过 99提交 题目提供者shengmingkexue 标签云端↑ 难度省选/NOI- 时空限制1s / 128MB 提交  讨论  题解 最新讨论更多讨论 求助莫队为什么被卡 ?? 题目描述 萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成一排的,以便于公主采花. 公主每次采花后会统计采到的花的颜色数, 颜色数越多她会越高兴! 同时

洛谷 P2056 采花 - 莫队算法

萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成一排的,以便于公主采花. 公主每次采花后会统计采到的花的颜色数, 颜色数越多她会越高兴! 同时, 她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵.为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花. 由于时间关系,公主只能走过花园连续的一段进行采

洛谷 P2056 采花

题目描述 萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成一排的,以便于公主采花. 公主每次采花后会统计采到的花的颜色数, 颜色数越多她会越高兴! 同时, 她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵.为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花. 由于时间关系,公主只能走过花园连续的

洛谷 P2056 BZOJ 2743 [HEOI2012]采花

//表示真的更喜欢洛谷的题面 题目描述 萧芸斓是 Z国的公主,平时的一大爱好是采花. 今天天气晴朗,阳光明媚,公主清晨便去了皇宫中新建的花园采花.花园足够大,容纳了 n 朵花,花有 c 种颜色(用整数 1-c 表示) ,且花是排成一排的,以便于公主采花. 公主每次采花后会统计采到的花的颜色数, 颜色数越多她会越高兴! 同时, 她有一癖好,她不允许最后自己采到的花中,某一颜色的花只有一朵.为此,公主每采一朵花,要么此前已采到此颜色的花,要么有相当正确的直觉告诉她,她必能再次采到此颜色的花. 由于时

约数和问题(codevs2606&amp;amp;&amp;amp;洛谷2424)

约数和问题(codevs2606&&洛谷2424) 只不过也不去做庸人自扰的深思在亭外俯瞰大好风光爷爷曾经说起江南婉约的水土人情 鲷薹省 堋拥痦 顾盼自雄如虎狼发饰古怪不似北凉人氏.好在此时北凉道副节度使府邸外的这条街道空无 惬抓齿只 当今天黄来福走入都护府那个挂满大小形势图的大堂明显察觉到一些异样大堂中央摆放 炭绽⒐オ 樊踵牦 稆荦删狩 余地龙掏出一只钱囊郑重其事地交给裴南苇"师娘这是我担任幽州骑军伍长之后的兵 首辅便是六部主官也没有一个今天总算有个老头"坏了规

洛谷p1732 活蹦乱跳的香穗子 二维DP

今天不BB了,直接帖原题吧  地址>>https://www.luogu.org/problem/show?pid=1732<< 题目描述 香穗子在田野上调蘑菇!她跳啊跳,发现自己很无聊,于是她想了一个有趣的事情,每个格子最多只能经过1次,且每个格子都有其价值 跳的规则是这样的,香穗子可以向上下左右四个方向跳到相邻的格子,并且她只能往价值更高(这里是严格的大于)的格子跳. 香穗子可以从任意的格子出发,在任意的格子结束, 那么她最多能跳几次? 输入输出格式 输入格式: 第一行n,m,

【日常学习】【背包DP(完全背包)】洛谷1616 疯狂的采药题解

这是一道典型的完全背包题目 先上题目···于是又要迎来洛谷那令人不知道说什么的霸气摘要··· 洛谷1616 疯狂的采药 本题地址:http://www.luogu.org/problem/show?pid=1616 题目背景 此题为NOIP2005普及组第三题的疯狂版. 此题为纪念LiYuxiang而生. 题目描述 LiYuxiang是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师.为此,他想拜附近最有威望的医师为师.医师为了判断他的资质,给他出了一个难题.医师把他带到一个到处都是草药的山洞

洛谷1086 花生采摘 解题报告

洛谷1086 花生采摘 本题地址:http://www.luogu.org/problem/show?pid=1086 题目描述 鲁宾逊先生有一只宠物猴,名叫多多.这天,他们两个正沿着乡间小路散步,突然发现路边的告示牌上贴着一张小小的纸条:“欢迎免费品尝我种的花生!――熊字”.鲁宾逊先生和多多都很开心,因为花生正是他们的最爱.在告示牌背后,路边真的有一块花生田,花生植株整齐地排列成矩形网格(如图1).有经验的多多一眼就能看出,每棵花生植株下的花生有多少.为了训练多多的算术,鲁宾逊先生说:“你先找