洛谷—— P2656 采蘑菇

https://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



容易发现当他可以来回走多次采蘑菇的时候,就是出现环的时候,那么就可以将这个环的所有能得到的蘑菇数处理出来。
一遍最短路求出ans、需要注意的是这里两个强连通分量连边时,因为边是有权值的,所以不能只连一条。
 1 #include <cstdio>
 2 #include <vector>
 3 #include <queue>
 4 
 5 #define min(a,b) (a<b?a:b)
 6 
 7 inline void read(int &x)
 8 {
 9     x=0; register char ch=getchar();
10     for(; ch>'9'||ch<'0'; ) ch=getchar();
11     for(; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
12 }
13 const int M(200005);
14 const int N(80005);
15 int n,m,s; double r;
16 int head[N],sumedge;
17 struct Edge {
18     int v,next,w;double r;
19     Edge(int v=0,int next=0,int w=0,double r=0.):v(v),next(next),w(w),r(r){}
20 }edge[M];
21 inline void ins(int u,int v,int w,double r)
22 {
23     edge[++sumedge]=Edge(v,head[u],w,r),head[u]=sumedge;
24 }
25 
26 int tim,low[N],dfn[N];
27 int top,Stack[N],instack[N];
28 int sumcol,col[N];
29 void DFS(int u)
30 {
31     low[u]=dfn[u]=++tim;
32     Stack[++top]=u,instack[u]=1;
33     for(int v,i=head[u]; i; i=edge[i].next)
34     {
35         v=edge[i].v;
36         if(!dfn[v]) DFS(v), low[u]=min(low[u],low[v]);
37         else if(instack[v]) low[u]=min(low[u],dfn[v]);
38     }
39     if(dfn[u]==low[u])
40     {
41         col[u]=++sumcol;
42         for(; u!=Stack[top]; --top)
43         {
44             col[Stack[top]]=sumcol;
45             instack[u]=0;
46         }
47         instack[u]=0; top--;
48     }
49 }
50 
51 int dis[N];
52 bool inq[N];
53 std::queue<int>que;
54 std::vector< std::pair<int,int> >vec[N];
55 inline int SPFA(int s)
56 {
57     int ret=-1; que.push(s);
58     for(int u,v,w; !que.empty(); )
59     {
60         u=que.front(); que.pop(); inq[u]=0;
61         for(int i=0; i<vec[u].size(); ++i)
62         {
63             v=vec[u][i].first,w=vec[u][i].second;
64             if(dis[v]>=dis[u]+w) continue;
65             dis[v]=dis[u]+w;
66             if(!inq[v]) inq[v]=1,que.push(v);
67         }
68     }
69     for(int i=1; i<=n; ++i) ret=ret>dis[i]?ret:dis[i];
70     return ret;
71 }
72 
73 int Presist()
74 {
75     read(n),read(m);
76     for(int u,v,w,i=1; i<=m; ++i)
77     {
78         read(u),read(v),read(w),
79         scanf("%lf",&r),ins(u,v,w,r);
80     }
81     for(int i=1; i<=n; ++i)
82         if(!dfn[i])    DFS(i);
83     for(int v,u=1; u<=n; ++u)
84         for(int i=head[u]; i; i=edge[i].next)
85         {
86             v=edge[i].v;
87             if(col[v]==col[u])
88                  for(int w=edge[i].w; w; w*=edge[i].r) dis[col[u]]+=w;
89             else vec[col[u]].push_back(std::make_pair(col[v],edge[i].w));
90         }
91     read(s); printf("%d
",SPFA(col[s]));
92     return 0;
93 }
94 
95 int Aptal=Presist();
96 int main(int argc,char**argv){;}
 
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。
原文地址:https://www.cnblogs.com/Shy-key/p/7732653.html