模板题
链接:https://www.luogu.org/problem/show?pid=2656
对于每条路,能多采就多采
每条路都有恢复系数
所以走完一遍仍然可以回来再采(如果有路)
显然要处理出环里的能采的最大值
处理成点权吧
然后缩成DAG
发现我可以跑最长路了
这题就是这样~
(这是学缩点的模板题QAQ)
更详细的解释:http://blog.csdn.net/loi_xczhw/article/details/49406781 //(2333学长博客)
Codes:
1 #include<iostream>
2 #include<cstring>
3 #include<cstdio>
4 #include<algorithm>
5 #include<stack>
6 using namespace std;
7 const int N = 200000 + 5;
8 const int N1 = 100000 + 5;
9 int n,m,head[N],nxt[N << 1],cnt,ff[N],tt[N],vv[N],S;
10 int scc[N],val[N],dis[N],dfn_c,dfn[N],low[N],huan_c,ans = -1;
11 double re[N];
12 struct Edge{
13 int ff,tt,vv;
14 double re;
15 }edge[N << 1];
16 void build(int f,int t,int v,double rec){
17 edge[++ cnt] = (Edge){f,t,v,rec};
18 nxt[cnt] = head[f];
19 head[f] = cnt;
20 return;
21 }
22 void clear(){
23 memset(head,0,sizeof(head));
24 memset(nxt,0,sizeof(nxt));
25 cnt = 0;
26 return;
27 }
28 stack <int> s;
29 void dfs(int x){
30 s.push(x);
31 dfn[x] = low[x] = ++ dfn_c;
32 for(int i = head[x];i;i = nxt[i]){
33 int t = edge[i].tt;
34 if(!dfn[t]){
35 dfs(t);
36 low[x] = min(low[t],low[x]);
37 }
38 else if(!scc[t]){
39 low[x] = min(low[x],dfn[t]);//关于这里是和low[t]还是dfn[t]取min好像是都可以
40 } //因为只要Low[x] != dfn[x] 即可,low[x]更新成什么不重要
41 } //你非要卡着dfn定义去理解也可以~
42 if(dfn[x] == low[x]){
43 ++ huan_c;
44 int tot = 0;
45 while(1){
46 int u = s.top();
47 s.pop();
48 scc[u] = huan_c;
49 if(u == x) break;
50 }
51 }
52 return;
53 }
54 bool vis[N1];
55 int get_val(int i){
56 int v = edge[i].vv;
57 int ans = v;
58 while(v){
59 v *= edge[i].re;
60 ans += v;
61 }
62 return ans;
63 }
64 deque <int> q;
65 void spfa(int x){ //最长路
66 memset(dis,0x80,sizeof(dis));//2139062144
67 while(!q.empty()) q.pop_front();
68 dis[x] = val[x];
69 q.push_back(x);
70 q.push_back(80001);
71 vis[x] = 1;
72 while(!q.empty()){
73 int u = q.front();
74 q.pop_front();
75 vis[u] = 0;
76 for(int i = head[u];i;i = nxt[i]){
77 int t = edge[i].tt;
78 int v = edge[i].vv;
79 if(dis[t] < dis[u] + v + val[t]){ //考虑点权
80 dis[t] = dis[u] + v + val[t];
81 if(vis[t])
82 continue;
83 if(!q.empty() && dis[t] > dis[q.front()])
84 q.push_front(t);
85 else if(!q.empty())
86 q.push_back(t);
87 vis[t] = 1;
88 }
89 }
90 }
91 return;
92 }
93 void buildd(){
94 for(int i = 1;i <= n;++ i){
95 for(int j = head[i];j;j = nxt[j]){
96 int t = tt[j];
97 if(scc[i] == scc[t]){
98 val[scc[i]] += get_val(j); //点权
99 }
100 }
101 }
102 clear();
103 for(int i = 1;i <= m;++ i){
104 int f = ff[i],t = tt[i];
105 if(scc[f] != scc[t]){
106 build(scc[f],scc[t],vv[i],re[i]);//缩点重建
107 }
108 }
109 }
110 void work(){
111 buildd(); //缩点
112 spfa(scc[S]);
113 for(int i = 1;i <= n;++ i){
114 ans = max(ans,dis[i]); // 求最长路
115 }
116 cout << ans << '
';
117 }
118 int main(){
119 // freopen("mushroom1.in","r",stdin);
120 // freopen("mushroom1.out","w",stdout);
121 scanf("%d%d",&n,&m);
122 for(int i = 1;i <= m;++ i){
123 scanf("%d%d%d%lf",&ff[i],&tt[i],&vv[i],&re[i]);
124 build(ff[i],tt[i],vv[i],re[i]);
125 }
126 scanf("%d",&S);
127 dfs(S);
128 work();
129 return 0;
130 }