1. 程式人生 > >洛谷—— P2656 采蘑菇

洛谷—— P2656 采蘑菇

一個數 得到 gist oid reg 新的 一次 tar next

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; 19 double r; 20 Edge(int v=0,int next=0,int w=0,double r=0.):v(v),next(next),w(w),r(r){} 21 }edge[M]; 22 inline void ins(int u,int v,int w,double r) 23 { 24 edge[++sumedge]=Edge(v,head[u],w,r),head[u]=sumedge; 25 } 26 27 int tim,low[N],dfn[N]; 28 int top,Stack[N],instack[N]; 29 int sumcol,col[N],point[N]; 30 void DFS(int u) 31 { 32 low[u]=dfn[u]=++tim; 33 Stack[++top]=u,instack[u]=1; 34 for(int v,i=head[u]; i; i=edge[i].next) 35 { 36 v=edge[i].v; 37 if(!dfn[v]) DFS(v), low[u]=min(low[u],low[v]); 38 else if(instack[v]) low[u]=min(low[u],dfn[v]); 39 } 40 if(dfn[u]==low[u]) 41 { 42 col[u]=++sumcol; 43 point[sumcol]++; 44 for(; u!=Stack[top]; --top) 45 { 46 col[Stack[top]]=sumcol; 47 point[sumcol]++; 48 instack[u]=0; 49 } 50 instack[u]=0; top--; 51 } 52 } 53 54 int dis[N]; 55 bool inq[N]; 56 std::queue<int>que; 57 std::vector< std::pair<int,int> >vec[N]; 58 inline int SPFA(int s) 59 { 60 int ret=-1; que.push(s); 61 for(int u,v,w; !que.empty(); ) 62 { 63 u=que.front(); que.pop(); inq[u]=0; 64 for(int i=0; i<vec[u].size(); ++i) 65 { 66 v=vec[u][i].first,w=vec[u][i].second; 67 if(dis[v]>=dis[u]+w) continue; 68 dis[v]=dis[u]+w; 69 if(!inq[v]) inq[v]=1,que.push(v); 70 } 71 } 72 for(int i=1; i<=n; ++i) ret=ret>dis[i]?ret:dis[i]; 73 return ret; 74 } 75 76 int Presist() 77 { 78 read(n),read(m); 79 for(int u,v,w,i=1; i<=m; ++i) 80 { 81 read(u),read(v),read(w), 82 scanf("%lf",&r),ins(u,v,w,r); 83 } 84 for(int i=1; i<=n; ++i) 85 if(!dfn[i]) DFS(i); 86 for(int v,u=1; u<=n; ++u) 87 for(int i=head[u]; i; i=edge[i].next) 88 { 89 v=edge[i].v; 90 if(col[v]==col[u]) 91 for(int w=edge[i].w; w; w*=edge[i].r) dis[col[u]]+=w; 92 else vec[col[u]].push_back(std::make_pair(col[v],edge[i].w)); 93 } 94 read(s); printf("%d\n",SPFA(col[s])); 95 return 0; 96 } 97 98 int Aptal=Presist(); 99 int main(int argc,char**argv){;}

洛谷—— P2656 采蘑菇