zoukankan      html  css  js  c++  java
  • BZOJ1179_APIO2009_抢掠计划_C++

      题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1179

      一道用 Tarjan 缩点+SPFA 最长路的题(Tarjan 算法:http://www.cnblogs.com/hadilo/p/5889333.html )

      我们可以这样考虑,把一个连通块缩成一个点,点权为所有权值和,且只要一个点有酒吧那么该点也就有酒吧

      因为当我们进入该连通块任意一个点时,显然把它里面所有的点都抢一遍才使答案最优,而且能回到原进入点,并且只要有一个有酒吧就可以选择在那里庆祝

      缩完点后,就可以用 SPFA 求最长路,边权变为点权,因为里面已经没有环了,所以可以用

      当然最大路也可以用 Dijkstra 或 DP 等方法做

      还有这道题细节很多很多,调了我4个多小时QuQ

     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cstdio>
     6 #include<cmath>
     7 #include<queue>
     8 #include<stack>
     9 #define N 500001
    10 using namespace std;
    11 
    12 int t,first[N],next[N],back[N],last[N],v[N],a[N],dfn[N],low[N],ans,d[N];
    13 bool f[N],g[N],b[N];
    14 stack<int> s;
    15 queue<int> q;
    16 void tarjan(int x)
    17 {
    18     dfn[x]=low[x]=++t;
    19     s.push(x);
    20     int i;
    21     for (i=first[x];i;i=next[i])
    22         {
    23             if (f[v[i]]) continue;
    24             if (dfn[v[i]]) low[x]=min(low[x],dfn[v[i]]);
    25             else
    26                 {
    27                     tarjan(v[i]);
    28                     low[x]=min(low[x],low[v[i]]);
    29                 }
    30         }
    31     if (dfn[x]==low[x])
    32         {
    33             int k,c=first[x];
    34             while (s.top()!=x)
    35                 {
    36                     i=c;
    37                     k=s.top();
    38                     f[k]=b[k]=1;
    39                     s.pop();
    40                     a[x]+=a[k];
    41                     g[x]|=g[k];
    42                     while (next[i]) i=next[i];
    43                     next[i]=first[k];
    44                     c=i;
    45                     for (i=last[k];i;i=back[i]) v[i]=x;
    46                 }
    47             f[s.top()]=1;
    48             s.pop();
    49         }
    50 }
    51 int main()
    52 {
    53     int n,m,i,x,k;
    54     scanf("%d%d",&n,&m);
    55     for (i=1;i<=m;i++)
    56         {
    57             scanf("%d%d",&x,&v[i]);
    58             next[i]=first[x];
    59             first[x]=i;
    60             back[i]=last[v[i]];
    61             last[v[i]]=i;
    62         }
    63     for (i=1;i<=n;i++)
    64         {
    65             scanf("%d",&a[i]);
    66             g[i]=b[i]=f[i]=0;
    67         }
    68     scanf("%d%d",&k,&m);
    69     for (i=1;i<=m;i++)
    70         {
    71             scanf("%d",&x);
    72             g[x]=1;
    73         }
    74     tarjan(k);
    75     for (i=1;i<=n;i++) f[i]=1;
    76     d[k]=a[k];
    77     q.push(k);
    78     while (!q.empty())
    79         {
    80             k=q.front();
    81             q.pop();
    82             if (g[k]) ans=max(ans,d[k]);
    83             for (i=first[k];i;i=next[i])
    84                 {
    85                     if (b[v[i]]||v[i]==k) continue;
    86                     if (d[v[i]]<d[k]+a[v[i]])
    87                         {
    88                             d[v[i]]=d[k]+a[v[i]];
    89                             q.push(v[i]);
    90                         }
    91                 }
    92         }
    93     cout<<ans<<endl;
    94     return 0;
    95 }

      这道题需要开无限栈,因为递归的 Tarjan 会爆栈,然而并不会手写栈

      BZOJ 上幸好开了无限栈,不然就 RE 了,不过其它的 OJ 好像没有开无限栈,RE 两个点……

      只好去网上下了一个代码,在 CodeVS 上交了一发手写栈的 Tarjan,终于A了orz(手写栈的戳这里: http://www.cnblogs.com/hadilo/p/5892791.html )

    版权所有,转载请联系作者,违者必究

    QQ:740929894

  • 相关阅读:
    js点击弹出div层
    图片按比例缩小
    js标题文字向上滚动
    JS刷新当前页面
    图片缩放显示,不变形
    产品叠加搜索
    Oracle中DML基础知识
    Oracle中DDL的基础知识
    Sql多对多关系中外键的应用
    oracle 中sql语句的几个基本函数..
  • 原文地址:https://www.cnblogs.com/hadilo/p/5892765.html
Copyright © 2011-2022 走看看