洛谷—— 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\n",SPFA(col[s])); 92 return 0; 93 } 94 95 int Aptal=Presist(); 96 int main(int argc,char**argv){;}
——每当你想要放弃的时候,就想想是为了什么才一路坚持到现在。