#include<iostream> #include<cstring> #include<cstdio> #include<stack> #include<queue> #include<cmath> using namespace std; struct in { int to,ne,co; }ter[200040]; double hui[200040]; bool flag[80080]; int n,m,x,y,z,s,ans[80080],f1[200020],l1[200020],c[200020],dfn[80080],low[80080],tot,ci,head[80080],tail,scc[80080],val[80080]; stack<int>sta; queue<int>qwq; inline void re(int &a) { a=0; char b=getchar(); bool flag=0; while(b<'0'||b>'9') { if(b=='-') flag=1; b=getchar(); } while(b>='0'&&b<='9') a=a*10+b-'0',b=getchar(); if(flag) a*=-1; } inline void init() { memset(head,-1,sizeof(head)); tail=0; } inline void build(int f,int l,int c) { ter[++tail]=(in){l,head[f],c},head[f]=tail; } void dfs(int r) { dfn[r]=low[r]=++ci;//先设初始值 sta.push(r); for(int i=head[r];i>0;i=ter[i].ne) { int t=ter[i].to; if(!dfn[t])//如果这个点没有访问过 { dfs(t); low[r]=min(low[r],low[t]);//在两个点能返回的层的最小值里面再取最小值 } else if(!scc[t])//如果这个点已经搜过但是没有判断在哪个环内 low[r]=min(low[r],dfn[t]); } if(dfn[r]==low[r])//如果说从这个点出发并且能够回来(包括自环) { tot++; while(1) { int h=sta.top(); sta.pop(); scc[h]=tot; if(h==r)//如果当前这个点已经被踢出 break;//结束 } } return; } inline int get_val(int x)//计算这个边的最大价值 { int rt=ter[x].co; while(ter[x].co) ter[x].co*=hui[x],rt+=ter[x].co; return rt; } inline void ret()//重新建边,设置点权 { for(int i=1;i<=n;i++) for(int j=head[i];j>0;j=ter[j].ne) if(scc[i]==scc[ter[j].to])//如果这两个点在同一个环里,加点权 val[scc[i]]+=get_val(j); init();//重新初始化建图 for(int i=1;i<=m;i++) if(scc[f1[i]]!=scc[l1[i]])//两者不同环,可以建边 build(scc[f1[i]],scc[l1[i]],c[i]); } void spfa()//像对普通点一样对于缩点后得到的dag跑最长路 { for(int i=1;i<=n;i++) ans[i]=-1000000007; while(!qwq.empty()) qwq.pop(); qwq.push(scc[s]),ans[scc[s]]=val[scc[s]],flag[scc[s]]=1; while(!qwq.empty()) { int qaq=qwq.front(); for(int i=head[qaq];i>0;i=ter[i].ne) { int t=ter[i].to; if(ans[t]<ans[qaq]+val[t]+ter[i].co) { ans[t]=ans[qaq]+val[t]+ter[i].co; if(!flag[t]) { qwq.push(t); flag[t]=1; } } } flag[qaq]=0; qwq.pop(); } int mx=0; for(int i=1;i<=n;i++)//答案要取最大值 mx=max(mx,ans[i]); printf("%d",mx); } int main() { re(n),re(m); init(); for(int i=1;i<=m;i++) re(f1[i]),re(l1[i]),re(c[i]),scanf("%lf",&hui[i]),build(f1[i],l1[i],c[i]); re(s); dfs(s);//tarjan缩环 ret();//重新建边 spfa();//跑最长路 return 0; }