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

    【题目描述】:
    抢掠计划

    【思路】:
    个人认为(APIO)考这种题完全是在搞笑,可能是怕有些选手一道题都(A)不了而设置的吧(比如我)。

    (tarjan)裸题,先缩点,在(DAG)上跑一遍(dp)决策出最大利益,因为终点处必须要有酒吧。所以最后在有酒吧的点处选最大值就可以了。。

    水水水。。

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int n,m,st,p;
    
    const int MAXN = 500005;
    
    struct edge{
        int u,v,nxt;
    }e[MAXN];int head[MAXN];int cnt = 0;int x[MAXN];int y[MAXN];int mon[MAXN];int pub[MAXN];
    int dfn[MAXN];int low[MAXN];int s[MAXN];int id = 0;int tot = 0;int Bcnt = 0;bool vis[MAXN];int b[MAXN];int val[MAXN];
    int dis[MAXN];bool r[MAXN];int bill[MAXN];
    
    inline void add(int u,int v){
        e[++cnt].u = u;e[cnt].v = v;e[cnt].nxt = head[u];head[u] = cnt;
    }
    
    inline void tarjan(int x){
        dfn[x] = low[x] = ++id;
        s[++tot] = x;vis[x] = 1;
    
        for(int i=head[x];i;i=e[i].nxt){
            int v = e[i].v;
            if(!dfn[v]){
                tarjan(v);
                low[x] = min(low[x] , low[v]);
            }
            else if (vis[v]) low[x] = min(low[x] , dfn[v]);
        }
    
        if(low[x] == dfn[x]){
            int j = -1;Bcnt++;
            while(j ^ x){
                j = s[tot--];
                vis[j] = 0;
                b[j] = Bcnt;
                val[Bcnt] += mon[j];
                if(pub[j]) bill[Bcnt] = 1;
            }
        }
    }
    
    queue<int>q;
    inline void spfa(){
        q.push(b[st]);
        memset(dis,-inf,sizeof dis);dis[b[st]] = val[b[st]];
        
        while(!q.empty()){
            int u = q.front();q.pop();r[u] = 0;
            for(int i=head[u];i;i=e[i].nxt){
                int v = e[i].v;
                if(dis[v] < dis[u] + val[v]){
                    dis[v] = dis[u] + val[v];
                    if(!r[v]){
                        q.push(v);
                        r[v] = 1;
                    }
                }
            }
        }
        
    //	for(int i=1;i<=Bcnt;++i) printf("%d ",dis[i]);
        int ans = -inf;
        for(int i=1;i<=Bcnt;++i){
            if(bill[i]) ans = max(ans , dis[i]);
        }
        printf("%d",ans);
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i){
            int u,v;scanf("%d%d",&u,&v);
            x[i] = u;y[i] = v;
            add(u,v);
        }
        for(int i=1;i<=n;++i) scanf("%d",&mon[i]);
        scanf("%d%d",&st,&p);
        for(int i=1;i<=p;++i){
            int o;scanf("%d",&o);
            pub[o] = 1;
        }
    
        for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
        
        memset(head,0,sizeof head);cnt = 0;
        for(int i=1;i<=m;++i) if(b[x[i]] ^ b[y[i]]) add(b[x[i]] , b[y[i]]);
        
        spfa();
        return 0;
    }
    
  • 相关阅读:
    Linux Ubuntu 忘记用户名和密码 解决办法
    C语言中标准输入流、标准输出流、标准错误输出流
    递归实现字符串反转char* reverse(char* str)合集
    (转)最好的求平方根的方法(精确度VS速度)Best Square Root Method Algorithm Function (Precision VS Speed)
    java验证码识别4
    互聯網產品設計主題詞表
    java验证码识别3
    C++实现C#的get,set属性操作
    简陋,山寨,Everything,桌面搜索,原理,源码
    java验证码识别1
  • 原文地址:https://www.cnblogs.com/lajioj/p/9691571.html
Copyright © 2011-2022 走看看