zoukankan      html  css  js  c++  java
  • P2656 采蘑菇 tarjan + spfa

    模板题

    链接: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 }

     

  • 相关阅读:
    Leetcode OJ: Rotate List
    Leetcode OJ: Reverse Words in a String
    Effective C++读书笔记
    word改变下划线与文字的距离
    sql 取出表中不重复的值
    Iso文件用utrliso怎么安装
    Spring注入aspectJ切面
    Spring中利用java注解声明切面
    Spring面向切面编程
    spring中部分异常
  • 原文地址:https://www.cnblogs.com/Loizbq/p/7685032.html
Copyright © 2011-2022 走看看