一个强连通分量里的所有蘑菇都可以被采完。
先缩点,得到一个DAG,拓扑排序,然后DP。
要注意拓扑排序的起点不是题目给的起点。
WA四个点的原因是精度不够,可以把恢复系x10用int存储,计算时再除以10。
#include<bits/stdc++.h>
using namespace std;
#define read(x) scanf("%d",&x)
#define maxn ((int)8e4)
#define inf 2147483647
struct Edge{
int y,z;
int k;
Edge() {}
Edge(int _y,int _z) {
y=_y,z=_z;
}
Edge(int _y,int _z,int _k) {
y=_y,z=_z,k=_k;
}
};
int n,m;
vector<Edge> a[maxn+5];
int pre[maxn+5],low[maxn+5],cnt=0;
stack<int> stk;
int col[maxn+5],sum=0;
vector<Edge> g[maxn+5];
int w[maxn+5];
int in[maxn+5];
queue<int> que;
int f[maxn+5];
bool use[maxn+5];
int topo(int s) {
for(int i=1;i<=sum;i++) {
if(!in[i]) que.push(i),use[i]=true;
f[i]=-inf;
}
f[s]=w[s];
while(!que.empty()) {
int x=que.front();que.pop();
for(int i=0;i<g[x].size();i++) {
int y=g[x][i].y,z=g[x][i].z+w[y];
f[y]=max(f[y],f[x]+z);
--in[y];
if(!use[y]&&!in[y]) {
use[y]=true;
que.push(y);
}
}
}
int ans=0;
for(int i=1;i<=sum;i++) ans=max(ans,f[i]);
return ans;
}
void make_graph() {
for(int i=1;i<=n;i++) {
for(int j=0;j<a[i].size();j++) {
Edge x=a[i][j];
if(col[i]==col[x.y]) {
int v=0;
while(x.z) {
v+=x.z;
x.z=int(x.k*x.z/10);
}
w[col[i]]+=v;
}
else g[col[i]].push_back(Edge(col[x.y],x.z)),in[col[x.y]]++;
}
}
}
void tarjan(int x) {
pre[x]=low[x]=++cnt;
stk.push(x);
for(int i=0;i<a[x].size();i++) {
int y=a[x][i].y;
if(!pre[y]) tarjan(y),low[x]=min(low[x],low[y]);
else if(pre[x]>pre[y]&&!col[y]) low[x]=min(low[x],pre[y]);
}
if(low[x]>=pre[x]) {
int u;
++sum;
do {
u=stk.top(),stk.pop();
col[u]=sum;
} while(u!=x);
}
}
int main() {
read(n),read(m);
for(int i=1;i<=m;i++) {
int x,y,z;
double k;
read(x),read(y),read(z);
scanf("%lf",&k);
a[x].push_back(Edge(y,z,k*10));
}
for(int i=1;i<=n;i++) {
if(!pre[i]) tarjan(i);
}
make_graph();
int s;
read(s);
s=col[s];
int ans=topo(s);
printf("%d",ans);
return 0;
}