zoukankan      html  css  js  c++  java
  • [APIO2009]抢掠计划

    嘟嘟嘟

    这题读完思路应该马上就有了。

    先强连通分量缩点,然后在DAG上dp求最长路即可,并且只在有酒吧的点更新答案。

    但是这样不一定正确。原因就是拓扑排序是每一次把入度为0的点加入队列,但对于每一个点的入度,我们重新建图的时候也算上了和起点不连通的点的贡献,导致入度变大,进而导致有些点无法dp到,使答案变小。

    所以可以只从起点跑一边tarjan,并且标记能跑到的点。然后重建图的时候特判即可。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 5e5 + 5;
     21 inline ll read()
     22 {
     23   ll ans = 0;
     24   char ch = getchar(), last = ' ';
     25   while(!isdigit(ch)) last = ch, ch = getchar();
     26   while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
     27   if(last == '-') ans = -ans;
     28   return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32   if(x < 0) x = -x, putchar('-');
     33   if(x >= 10) write(x / 10);
     34   putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, s, p, a[maxn];
     38 bool bar[maxn];
     39 struct Edge
     40 {
     41   int nxt, to;
     42 }e[maxn];
     43 int head[maxn], ecnt = -1;
     44 void addEdge(int x, int y)
     45 {
     46   e[++ecnt] = (Edge){head[x], y};
     47   head[x] = ecnt;
     48 }
     49 
     50 int dfn[maxn], low[maxn], cnt = 0;
     51 int st[maxn], top = 0;
     52 bool in[maxn], bel[maxn], vis[maxn];
     53 int col[maxn], ccol = 0;
     54 ll val[maxn];
     55 void tarjan(int now)
     56 {
     57   dfn[now] = low[now] = ++cnt;
     58   st[++top] = now; in[now] = 1;
     59   for(int i = head[now], v; i != -1; i = e[i].nxt)
     60     {
     61       v = e[i].to;
     62       if(!dfn[v])
     63     {
     64       tarjan(v);
     65       low[now] = min(low[now], low[v]);
     66     }
     67       else if(in[v]) low[now] = min(low[now], dfn[v]);
     68     }
     69   if(dfn[now] == low[now])
     70     {
     71       int x; ccol++;
     72       do
     73     {
     74       x = st[top--];
     75       in[x] = 0;
     76       col[x] = ccol;
     77       val[ccol] += a[x];
     78       bel[ccol] = 1;
     79       if(bar[x]) vis[ccol] = 1;
     80     }while(x != now);
     81     }
     82 }
     83 
     84 Edge e2[maxn];
     85 int head2[maxn], ecnt2 = -1;
     86 int du[maxn];
     87 void addEdge2(int x, int y)
     88 {
     89   e2[++ecnt2] = (Edge){head2[x], y};
     90   head2[x] = ecnt2;
     91 }
     92 void newGraph(int now)
     93 {
     94   int u = col[now];
     95   if(!bel[u]) return;
     96   for(int i = head[now], v; i != -1; i = e[i].nxt)
     97     {
     98       v = col[e[i].to];
     99       if(u != v && bel[v]) addEdge2(u, v), du[v]++;
    100     }
    101 }
    102 
    103 ll dp[maxn], ans = 0;
    104 void topo(int s)
    105 {
    106   queue<int> q; q.push(s);
    107   dp[s] = val[s];
    108   if(vis[s]) ans = dp[s];
    109   while(!q.empty())
    110     {
    111       int now = q.front(); q.pop();
    112       for(int i = head2[now], v; i != -1; i = e2[i].nxt)
    113     {
    114       v = e2[i].to;
    115       dp[v] = max(dp[v], dp[now] + val[v]);
    116       if(vis[v]) ans = max(ans, dp[v]);
    117       if(--du[v] == 0) q.push(v);
    118     }
    119     }
    120 }
    121 
    122 int main()
    123 {
    124   Mem(head, -1);
    125   n = read(); m = read();
    126   for(int i = 1; i <= m; ++i)
    127     {
    128       int x = read(), y = read();
    129       addEdge(x, y);
    130     }
    131   for(int i = 1; i <= n; ++i) a[i] = read();
    132   s = read(); p = read();
    133   for(int i = 1; i <= p; ++i) {int x = read(); bar[x] = 1;}
    134   tarjan(s);
    135   Mem(head2, -1);
    136   for(int i = 1; i <= n; ++i) newGraph(i);
    137   topo(col[s]);
    138   write(ans), enter;
    139   return 0;
    140 }
    View Code
  • 相关阅读:
    蚂蚁问题
    LinuxC安装gcc
    怎样在VC里面使用graphics.h绘图
    C语言之固定格式输出当前时间
    C语言之猜数字游戏
    C语言之新同学年龄
    C语言之ASCII码
    C语言之辗转相除法
    C语言之自守数
    C语言之一数三平方
  • 原文地址:https://www.cnblogs.com/mrclr/p/9948705.html
Copyright © 2011-2022 走看看