bzoj 1179

题意:给你一个有向图,每个点有一个权值,有一个起点和q个终点,没经过一个点加上这个点的权值,让你选一条路,问你最大值是多少。

 

思路:tarjan强连通缩个点, 然后在拓扑图上dp一下就好啦, 注意第二次建图建反向边会好一点。

  1 #include<bits/stdc++.h>
  2 #define LL long long
  3 #define fi first
  4 #define se second
  5 #define mk make_pair
  6 #define pii pair<int,int>
  7 
  8 using namespace std;
  9 
 10 const int N=5e5+7;
 11 const int M=1e4+7;
 12 const int inf=0x3f3f3f3f;
 13 const LL INF=0x3f3f3f3f3f3f3f3f;
 14 const int mod=1e9 + 7;
 15 
 16 struct edge {
 17     int from, to, nx;
 18 }e[N];
 19 bool bar[N], flag[N], in[N], ok[N];
 20 int n, m, tot, cnt, S, p, idx, top, head[N], a[N], sum[N], dfn[N], low[N], id[N], f[N], st[N];
 21 
 22 vector<int> edge[N];
 23 void add(int from, int to) {
 24     e[tot].from = from;
 25     e[tot].to = to;
 26     e[tot].nx = head[from];
 27     head[from] = tot++;
 28 }
 29 
 30 void tarjan(int u) {
 31     ++idx;
 32     dfn[u] = low[u] = idx;
 33     st[top++] = u; in[u] = true;
 34     for(int i = head[u]; ~i; i = e[i].nx) {
 35         int v = e[i].to;
 36         if(!dfn[v]) {
 37             tarjan(v);
 38             low[u] = min(low[u], low[v]);
 39         } else if(in[v]) {
 40             low[u] = min(low[u], dfn[v]);
 41         }
 42     }
 43     if(low[u] == dfn[u]) {
 44         cnt++;
 45         while(1) {
 46             int now = st[--top];
 47             in[now] = false;
 48             id[now] = cnt;
 49             if(now == u) break;
 50         }
 51     }
 52 }
 53 
 54 int dp(int u) {
 55     if(f[u] != -1) return f[u];
 56     f[u] = 0;
 57     for(int i = 0; i < edge[u].size(); i++) {
 58         int v = edge[u][i];
 59         int ret = dp(v);
 60         if(ok[v]) {
 61             ok[u] = true;
 62             f[u] = max(f[u], f[v]);
 63         }
 64     }
 65     if(!ok[u]) return f[u];
 66     return f[u] = f[u] + sum[u];
 67 }
 68 int main() {
 69     memset(head, -1, sizeof(head));
 70     memset(f, -1, sizeof(f));
 71     scanf("%d%d", &n, &m);
 72     for(int i = 1; i <= m; i++) {
 73         int from, to; scanf("%d%d", &from, &to);
 74         add(from, to);
 75     }
 76     for(int i = 1; i <= n; i++)
 77         scanf("%d", &a[i]);
 78 
 79     scanf("%d%d", &S, &p);
 80     for(int i = 1; i <= p; i++) {
 81         int x; scanf("%d", &x);
 82         flag[x] = true;
 83     }
 84     for(int i = 1; i <= n; i++) {
 85         if(!dfn[i]) tarjan(i);
 86     }
 87     for(int i = 1; i <= n; i++) {
 88         sum[id[i]] += a[i];
 89         bar[id[i]] |= flag[i];
 90     }
 91     for(int i = 0; i < tot; i++) {
 92         int u = e[i].from, v = e[i].to;
 93         if(id[u] != id[v]) {
 94             edge[id[v]].push_back(id[u]);
 95         }
 96     }
 97     S = id[S];
 98     ok[S] = true;
 99     int ans = 0;
100     for(int i = 1; i <= cnt; i++) {
101         if(bar[i]) {
102             ans = max(ans, dp(i));
103         }
104     }
105     printf("%d\n", ans);
106     return 0;
107 }
108 /*
109 */

 

posted @ 2018-05-07 17:01  NotNight  阅读(129)  评论(0编辑  收藏  举报