洛谷——P2656 采蘑菇
题目描述
小胖和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范围内。
输入输出样例
比较水,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; }
博主蒟蒻,若有出错的地方,敬请指出。
如有侵犯您版权的地方,请快速联系我,我会撤回本博文。