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

洛谷——P2656 采蘑菇

stack 最短 ret return spa orange code 輸出 nbsp

題目描述

小胖和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縮點+spfa最長路(把邊權取反,求最短路)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
#include<queue>
#define N 10101010

using namespace std;

int n,m,head[N],tot,tpt,phead[N],w[N],s,ans;
struct bode{
    int to,next,w;
    
double f; }e[N],p[N]; void add(int u,int v,int w,double f,bool flg){ if(flg) e[++tot].to=v,e[tot].next=head[u],head[u]=tot,e[tot].w=w,e[tot].f=f; else p[++tpt].to=v,p[tpt].next=phead[u],phead[u]=tpt,p[tpt].w=w,p[tpt].f=f; } int dfn[N],low[N],item,cnt,belong[N]; bool vis[N]; stack<int>S; void tarjan(int u){ dfn[u]=low[u]=++item; vis[u]=1;S.push(u); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(!dfn[v]){ tarjan(v); low[u]=min(low[u],low[v]); }else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]){ int v=u;++cnt; do{ v=S.top();S.pop(); vis[v]=0;belong[v]=cnt; }while(v!=u); } } int wh(int W,double f){ int an=0; while(W){ an+=W; W*=f; } return an; } queue<int>Q; int d[N]; void spfa(){ memset(vis,0,sizeof(vis)); // memset(d,0x3f,sizeof(d)); Q.push(belong[s]);vis[belong[s]]=1;d[belong[s]]=-w[belong[s]]; // for(int i=1;i<=cnt;i++) d[i]-=w[i]; while(!Q.empty()){ int u=Q.front();Q.pop();vis[u]=0; for(int i=phead[u];i;i=p[i].next){ int v=p[i].to; if(d[v]>d[u]-p[i].w){ d[v]=d[u]-p[i].w; d[v]-=w[v];w[v]=0; if(!vis[v]){ Q.push(v); vis[v]=1; } } } } } int main() { scanf("%d%d",&n,&m); for(int u,v,W,i=1;i<=m;i++){ double f; scanf("%d%d%d%lf",&u,&v,&W,&f); add(u,v,W,f,1); } for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); for(int i=1;i<=n;i++){ for(int j=head[i];j;j=e[j].next){ int v=e[j].to; if(belong[v]!=belong[i]){ add(belong[i],belong[v],e[j].w,0,0); }else w[belong[i]]+=wh(e[j].w,e[j].f); } } scanf("%d",&s); spfa(); for(int i=1;i<=n;i++) ans=max(ans,-d[i]); printf("%d\n",ans); return 0; }

洛谷——P2656 采蘑菇