码迷,mamicode.com
首页 > Windows程序 > 详细

APIO2009劫掠计划

时间:2018-06-28 21:58:30      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:pac   AC   void   namespace   set   ios   while   ret   FN   

/*
缩点加上最长路
应该用拓扑序列的  不想写  spfa跑一下吧



*/

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
#define M 500200
#define ll long long
using namespace std;
int be[M], ed[M], to[M], nxt[M], dft, head[M], cnt, belong[M], dfn[M], low[M], dis[M], ver[M], ver2[M], st[M], top, tot;
bool vis[M], isj[M], zz[M];

int read() {
    int nm = 0, f = 1;
    char c = getchar();
    for(; !isdigit(c); c = getchar()) if(c == -) f = -1;
    for(; isdigit(c); c = getchar()) nm = nm * 10 + c -0;
    return nm * f;
}

void push(int vi, int vj) {
    cnt++;
    to[cnt] = vj;
    nxt[cnt] = head[vi];
    head[vi] = cnt;
}

void tarjan(int x) {
    dfn[x] = low[x] = ++dft;
    st[++top] = x;
    vis[x] = true;
    for(int i = head[x]; i; i = nxt[i]) {
        int vj = to[i];
        if(!dfn[vj]) {
            tarjan(vj);
            low[x] = min(low[x], low[vj]);
        } else if(vis[vj]) low[x] = min(low[x], dfn[vj]);
    }
    if(dfn[x] == low[x]) {
        tot++;
        while(st[top] != x) {
            belong[st[top]] = tot;
            ver2[tot] += ver[st[top]];
            if(isj[st[top]]) zz[tot] = true;
            vis[st[top]] = false;
            top--;
        }

        belong[st[top]] = tot;
        ver2[tot] += ver[st[top]];
        if(isj[st[top]]) zz[tot] = true;
        vis[st[top]] = false;
        top--;
    }
}

void spfa(int x) {
    queue<int>q;
    dis[x] = ver2[x];
    memset(vis, 0, sizeof(vis));
    q.push(x);
    while(!q.empty()) {
        int op = q.front();
        q.pop();
        vis[op] = false;
        for(int i = head[op]; i; i = nxt[i]) {
            int vj = to[i];
            if(dis[vj] < dis[op] + ver2[vj]) {
                dis[vj] = dis[op] + ver2[vj];
                if( !vis[vj])
                    q.push(vj), vis[vj] = true;
            }
        }
    }
}


int main() {
    int n = read(), m = read();
    for(int i = 1; i <= m; i++) {
        be[i] = read(), ed[i] = read();
        push(be[i], ed[i]);
    }
    for(int i = 1; i <= n; i++) ver[i] = read();
    int s = read(), k = read();
    for(int i = 1; i <= k; i++) isj[read()] = true;
    tarjan(s);
    memset(head, 0, sizeof(head));
    cnt = 0;
    for(int i = 1; i <= m; i++) {
        int vi = belong[be[i]], vj = belong[ed[i]];
        if(vi == vj) continue;
        push(vi, vj);
    }
    spfa(belong[s]);
    int ans=  0;
    for(int i = 1; i <= tot; i++) {
        if(zz[i]) ans = max(ans, dis[i]);
    }
    cout << ans;
    return 0;
}

 

APIO2009劫掠计划

标签:pac   AC   void   namespace   set   ios   while   ret   FN   

原文地址:https://www.cnblogs.com/luoyibujue/p/9240866.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!