• [NOIP2009提高组]最优贸易 tarjan题解


    今天刚刚学会了用tarjan写缩点(以前用两遍dfs写的),此题调了我很久,需要考虑的情况有些多,但是做出来还是挺开心的。

    首先通过tarjan缩点,之后要干的事情就是计算答案。

    答案有两种情况,一是在一个联通块中买进卖出,二是在一个联通块中买入,但在另外一个联通块中卖出。但是需要注意的是,以上两种情况中的联通块需要满足起点可以到达它,它也可以到达终点,并且不在一个联通块中时,买进必在卖出前。

    代码中的dp(x)记录的是从起点到现在买进价最低的,每次只要用当前最大价钱减去这个值,再去和ans做比较,就是第二种情况,而第一种情况还是非常好写的。

    下面是我的代码,请无视那么多的注释(调试信息)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<vector>
      4 using namespace std;
      5 const int maxn=100005;
      6 const int maxm=1000005;
      7 int dfn[maxn],low[maxn],st[maxn];
      8 bool instack[maxn];
      9 int now;
     10 int n,m;
     11 int cnt;
     12 int to[maxm],next[maxm],head[maxn];
     13 int dp[maxn];
     14 int col[maxn];
     15 int small[maxn],big[maxn];
     16 int val[maxn];
     17 int p[maxn];
     18 int u[maxm],h[maxm];
     19 int color;
     20 int tim=0;
     21 int vis[maxn];
     22 void add(int x,int y)
     23 {
     24     cnt++;
     25     to[cnt]=y;
     26     next[cnt]=head[x];
     27     head[x]=cnt;
     28 }
     29 vector <int >v[maxn],all;
     30 vector <int > g[maxn];
     31 void tarjan(int x)
     32 {
     33     dfn[x]=low[x]=++tim;
     34     st[++now]=x;
     35     instack[x]=true;
     36     for(int i=head[x];i;i=next[i])
     37     {
     38           if(!dfn[to[i]])
     39           {
     40               tarjan(to[i]);
     41              low[x]=min(low[x],low[to[i]]);    
     42          }
     43          else if(instack[to[i]])
     44          {
     45              low[x]=min(low[x],dfn[to[i]]);
     46          }
     47     }
     48 //    cout<<x<<" "<<low[x]<<" "<<dfn[x]<<endl;
     49     if(low[x]==dfn[x])
     50     {
     51     //    cout<<x<<endl;
     52         color++;
     53         int j=-1;
     54         small[color]=19991231;
     55         do
     56         {
     57             j=st[now--];
     58             big[color]=max(big[color],val[j]);
     59             small[color]=min(small[color],val[j]);
     60             instack[j]=false;
     61             col[j]=color;
     62         }while(x!=j);
     63     }
     64 }    
     65 int out[maxn];
     66 int ans;
     67 int ss[maxn];
     68 void dfs(int x)
     69 {
     70 //    cout<<x<<endl;
     71     vis[x]=true;
     72     for(int i=0;i<g[x].size();i++)
     73     {
     74         //cout<<x<<" "<<g[x][i]<<endl;
     75         if(!vis[g[x][i]])
     76         {
     77             dfs(g[x][i]);
     78         }
     79     }
     80 }
     81 void dfss(int x)
     82 {
     83     ss[x]=true;
     84     for(int i=0;i<v[x].size();i++)
     85     {
     86         //cout<<x<<" "<<g[x][i]<<endl;
     87         if(!ss[v[x][i]])
     88         {
     89             dfss(v[x][i]);
     90         }
     91     }
     92 }
     93 int solve(int x)
     94 {
     95     //cout<<x<<" ";
     96     if(dp[x])return dp[x];
     97     dp[x]=small[x];
     98     //cout<<x<<" "<<dp[x]<<endl;
     99     for(int i=0;i<v[x].size();i++)
    100     {
    101         //cout<<x<<" "<<v[x][i]<<endl;
    102         if(!vis[v[x][i]] || !ss[v[x][i]] )continue;
    103         if(v[x][i]==x)continue;
    104     //    cout<<dp[x]<<endl;
    105         dp[x]=min(dp[x],solve(v[x][i]));
    106     //    cout<<v[x][i]<<" "<<dp[x]<<" "<<solvedp[v[x][i]]<<endl;
    107     }
    108 //    cout<<x<<" "<<dp[x]<<endl;
    109 //    cout<<x<<" "<<dp[x]<<" "<<big[x]<<endl;
    110     if(big[x]-dp[x]>ans)ans=big[x]-dp[x];
    111     //cout<<x<<" "<<ans<<endl;
    112     return dp[x];
    113 }
    114 int main()
    115 {
    116     scanf("%d%d",&n,&m);
    117     for(int i=1;i<=n;i++)scanf("%d",&val[i]);
    118     for(int i=1;i<=m;i++)
    119     {
    120         int x,y,z;
    121         scanf("%d%d%d",&x,&y,&z);
    122         add(x,y);
    123         if(z!=1)add(y,x);
    124         u[i]=x;
    125         h[i]=y;
    126     }
    127 //    cout<<endl;
    128 
    129     for(int i=1;i<=n;i++)
    130     {
    131         if(!dfn[i])
    132         {
    133             tarjan(i);
    134         }
    135     }
    136 //    cout<<col[1]<<endl;
    137     for(int i=1;i<=m;i++)
    138     {
    139         if(col[u[i]]!=col[h[i]])
    140         {
    141         //    cout<<col[u[i]]<<" "<<col[h[i]]<<endl;
    142             v[col[h[i]]].push_back(col[u[i]]);
    143             g[col[u[i]]].push_back(col[h[i]]);
    144         }
    145     }
    146 //    cout<<col[5]<<endl;
    147 //    cout<<color<<endl;
    148 //for(int i=1;i<=n;i++)cout<<i<<" "<<col[i]<<endl;
    149     //for(int i=1;i<=color;i++)cout<<big[i]<<" "<<small[i]<<endl;
    150     dfs(col[1]);
    151     dfss(col[n]);
    152 //    for(int i=1;i<=color;i++)cout<<i<<" "<<vis[i]<<endl;
    153 //    cout<<ans<<endl;
    154 //    cout<<color<<endl;
    155     int tmp=solve(col[n]);
    156 //    cout<<ans<<endl;
    157     for(int i=1;i<=color;i++)
    158     {
    159         if(vis[i] && ss[i])ans=max(ans,big[i]-small[i]);
    160     //    cout<<big[i]-small[i]<<endl;
    161         //cout<<vis[i]<<" "<<big[i]<<" "<<small[i]<<endl;
    162     }
    163     if(!vis[col[n]] || !ss[col[1]])ans=0;
    164 //    cout<<vis[col[n]];
    165     printf("%d
    ",ans);
    166     return 0;
    167 }
    View Code
  • 相关阅读:
    css 写一个三角形
    vue 知识汇总,中级阶段的。
    获取url参数封装的
    vue 知识点
    不换行css
    微信小程序的横向滚动
    git提交本地分支到远程分支
    linux shell head tail 用法简介
    PHP服务重启
    MongoDB用户创建
  • 原文地址:https://www.cnblogs.com/sillygirl/p/3907308.html
Copyright © 2020-2023  润新知