Codevs1161 抢掠计划

来源:互联网 发布:在线打电话软件 编辑:程序博客网 时间:2024/06/06 04:36
  • 前言:这题A得挺值,不仅学会了tarjan以及递归转非递归,还熟悉了spfa,不错。

  • 鸣谢:hzwer、t14t41t。

  • 题目大意:给定一张有向有环图,有点权,求一条路上得到点权的最大值。

  • 思路:一个强连通分量里的点权是全部能取得的,因此用tarjan进行缩点。最后求值时,可以用spfa求最长路,个人感觉也可以用拓扑序递推,我用的是spfa,具体的在程序中解释。

  • 代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<vector>#include<stack>using namespace std;const int maxn=600005;int n,m,source,p;vector<int> g[maxn],rg[maxn];/*g是原图,rg是重建图*/int atm[maxn],pub[maxn];stack<int> s,bs;/*s是tarjan的栈,bs是模拟系统栈*/int dex,cir=0,dfn[maxn],low[maxn],belong[maxn];int sum[maxn];bool in[maxn];void init(){     memset(dfn,0,sizeof(dfn));     memset(low,0,sizeof(low));     memset(in,0,sizeof(in));     scanf("%d%d",&n,&m);     for (int i=1;i<=m;++i)     {         int a,b;         scanf("%d%d",&a,&b);         g[a].push_back(b);     }     for (int i=1;i<=n;++i)       scanf("%d",&atm[i]);     scanf("%d%d",&source,&p);     for (int i=1;i<=p;++i)       scanf("%d",&pub[i]);}/*void tarjan(int u){     low[u]=dfn[u]=++dex;     s.push(u);     in[u]=1;      for (int i=0;i<g[u].size();++i)     {         if (!dfn[g[u][i]])         {             tarjan(g[u][i]);             low[u]=min(low[u],low[g[u][i]]);         }         else         {             if (in[g[u][i]])             {                 low[u]=min(low[u],dfn[g[u][i]]);             }         }     }     if (low[u]==dfn[u])     {         cir++;         int t=-1;         while (t!=u)         {               t=s.top();               s.pop();               in[t]=0;               belong[t]=cir;               sum[cir]+=atm[t];         }     }}*/       /*递归版tarjan*/void tarjan(int u){     dfn[u]=low[u]=++dex;     bs.push(u);     s.push(u);     in[u]=1;     while (!bs.empty())     {            int t=bs.top();            for (int i=0;i<g[t].size();++i)            {                if (!dfn[g[t][i]])                {                    dfn[g[t][i]]=low[g[t][i]]=++dex;                    bs.push(g[t][i]);                    in[g[t][i]]=1;                    s.push(g[t][i]);                    break;                /*在这里break,会有下面t!=top(),从而一直递归下去*/                }            }            if (t==bs.top())            {                for (int i=0;i<g[t].size();++i)                {                    if (dfn[g[t][i]]>dfn[t])                    /*这里需要判断是不是后来的,递归版则不需要*/                      low[t]=min(low[t],low[g[t][i]]);                    else                      if (in[g[t][i]])                        low[t]=min(low[t],dfn[g[t][i]]);                }                if (dfn[t]==low[t])                {                    cir++;                    int now=-1;                    while (now!=t)                    {                        now=s.top();                        belong[now]=cir;                        sum[cir]+=atm[now];                        in[now]=0;                        s.pop();                    }                }                bs.pop();            }     }}void rebuild(){     for (int i=1;i<=n;++i)       for (int j=0;j<g[i].size();++j)         if (belong[i]!=belong[g[i][j]])           rg[belong[i]].push_back(belong[g[i][j]]);}int vis[maxn],fee[maxn];queue<int> q;void spfa(int s){     memset(vis,0,sizeof(vis));     memset(fee,0,sizeof(fee));     q.push(s);     vis[s]=1;     fee[s]=sum[s];     while (!q.empty())     {           int h=q.front();           vis[h]=0;           q.pop();           for (int i=0;i<rg[h].size();++i)           {               if (fee[rg[h][i]]<fee[h]+sum[rg[h][i]])               {                   fee[rg[h][i]]=fee[h]+sum[rg[h][i]];                   if (!vis[rg[h][i]])                   {                       vis[rg[h][i]]=1;                       q.push(rg[h][i]);                   }               }           }        }     int ans=0;     for (int i=1;i<=p;++i)     {         ans=max(ans,fee[belong[pub[i]]]);     }     printf("%d",ans);}int main(){    init();    for (int i=1;i<=n;++i)      if (!dfn[i])      {          /*不要写dex=0*/          tarjan(i);      }    rebuild();    spfa(belong[source]);    return 0;}
0 0
原创粉丝点击