zoukankan      html  css  js  c++  java
  • luogu1073 最优贸易 (tarjan+dp)

    tarjan缩点,然后按照拓扑序,做1号点能到达的点的答案
    具体做法是对每个点记一个min[i],max[i],vis[i]和ans[i]
    做拓扑序的时候,假设在从u点开始做,有边u到v,如果vis[u]=1,则则
    vis[v]=1(初始时vis[bel[1]]=1);
    更新在v点及以前买进的最小进价:min[v]=min{min[v],min[u]}
    统计在v点卖出的答案:ans[v]=max{ans[u],ans[v],max[v]-min[v]}
    则最后答案就是ans[bel[N]]

    貌似还有做两遍spfa的做法...不管了

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<vector>
     6 #define LL long long int
     7 #define inf 0x3f3f3f3f
     8 using namespace std;
     9 const int maxn=100010,maxm=1000010;
    10 
    11 LL rd(){
    12     LL x=0;char c=getchar();int neg=1;
    13     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
    14     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
    15     return x*neg;
    16 }
    17 
    18 int N,M;
    19 int eg[maxm][2],egh[maxn],ect;
    20 int eg2[maxm][2],egh2[maxn],ect2;
    21 int val[maxn],in[maxn],bel[maxn];
    22 int dfn[maxn],low[maxn],stk[maxn],sct,tot,pct;
    23 int mi[maxn],ma[maxn],ans[maxn];
    24 vector<int> hav[maxn];
    25 bool instk[maxn],flag[maxn],vis[maxn];
    26 
    27 inline void adeg(int a,int b){
    28     eg[ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect++;
    29 }
    30 inline void adeg2(int a,int b){
    31     eg2[ect2][0]=b;eg2[ect2][1]=egh2[a];egh2[a]=ect2++;
    32     in[b]++;
    33 }
    34 
    35 void tarjan(int x){
    36     dfn[x]=low[x]=++tot;instk[x]=1;stk[++sct]=x;
    37     for(int i=egh[x];i!=-1;i=eg[i][1]){
    38         int j=eg[i][0];
    39         if(instk[j]) low[x]=min(low[x],dfn[j]);
    40         else if(!dfn[j]) {
    41             tarjan(j);low[x]=min(low[x],low[j]);
    42         }
    43     }if(dfn[x]==low[x]){
    44         pct++;mi[pct]=inf;ma[pct]=-inf;
    45         while(sct){
    46             mi[pct]=min(mi[pct],val[stk[sct]]);
    47             ma[pct]=max(ma[pct],val[stk[sct]]);
    48             bel[stk[sct]]=pct;
    49             instk[stk[sct]]=0;
    50             hav[pct].push_back(stk[sct]);
    51             if(stk[sct--]==x) break;
    52         }
    53     }
    54 }
    55 
    56 
    57 int main(){
    58     int i,j,k;
    59     //freopen("testdata.in","r",stdin);
    60     N=rd(),M=rd();
    61     for(i=1;i<=N;i++) val[i]=rd();
    62     memset(egh,-1,sizeof(egh));memset(egh2,-1,sizeof(egh2));
    63     for(i=1;i<=M;i++){
    64         int a=rd(),b=rd(),c=rd();
    65         adeg(a,b);if(c==2) adeg(b,a);
    66     }for(i=1;i<=N;i++) if(!dfn[i]) tarjan(i);
    67     
    68     for(i=1;i<=pct;i++){
    69         memset(flag,0,pct+5);
    70         for(j=0;j<hav[i].size();j++){
    71             for(k=egh[hav[i][j]];k!=-1;k=eg[k][1]){
    72                 if(i==bel[eg[k][0]]) continue;
    73                 if(!flag[bel[eg[k][0]]]) adeg2(i,bel[eg[k][0]]);
    74                 flag[bel[eg[k][0]]]=1;
    75             }
    76         }
    77     }
    78     queue<int> q;vis[bel[1]]=1;
    79     for(i=1;i<=pct;i++){
    80         if(!in[i]) q.push(i);
    81     }
    82     while(!q.empty()){
    83         int p=q.front();q.pop();
    84         for(i=egh2[p];i!=-1;i=eg2[i][1]){
    85             j=eg2[i][0];
    86             if(vis[p]){
    87                 vis[j]=1;ans[j]=max(ans[j],ans[p]);
    88                 mi[j]=min(mi[j],mi[p]);
    89                 ans[j]=max(ans[j],ma[j]-mi[j]);
    90             }
    91             if(!(--in[j])) q.push(j);
    92         }
    93     }
    94     printf("%d
    ",ans[bel[N]]);
    95 }
  • 相关阅读:
    dotnet 新项目格式与对应框架预定义的宏
    dotnet 线程静态字段
    dotnet 线程静态字段
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 拿到显卡信息
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取指定进程的输入命令行
    dotnet 通过 WMI 获取系统信息
    dotnet 通过 WMI 获取系统信息
    PHP show_source() 函数
  • 原文地址:https://www.cnblogs.com/Ressed/p/9409527.html
Copyright © 2011-2022 走看看