洛谷——P2656 采蘑菇

 

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范围内。

 

输入输出样例

输入样例#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;
}

 

posted @ 2018-09-01 19:57  清风我已逝  阅读(175)  评论(0编辑  收藏  举报