zoukankan      html  css  js  c++  java
  • 【bzoj1179】 Apio2009—Atm

    www.lydsy.com/JudgeOnline/problem.php?id=1179 (题目链接)

    题意

      给出一张有向图,每个节点有点权。标记一些点,找出一条路径,可以重复经过一条边,使得总点权和最大。重复经过一个点不能重复算点权。

    Solution

      今日考试题,Dijkstra不幸Gi烂。

      WARNING:Dijkstra处理最长路时会出现一些不好的情况,所以千万不要用!!

      既然可以重复经过一些边,那么一旦经过了某个环,我们一定可以把环上所有的点跑遍,所以做法就很显然了。先Tarjan缩点,所以整个图就变成有向无环图,跑DP或者SPFA最长路即可。

    代码

    // bzoj1179
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define LL long long
    #define inf 2147483640
    #define Pi acos(-1.0)
    #define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
    using namespace std;
    
    const int maxn=500010;
    struct data {
        int num,x;
        friend bool operator < (const data &x,const data &y) {
            return x.x<y.x;
        }
    };
    struct edge {int to,next;}e[maxn<<1];
    struct E {int u,v;}ee[maxn];
    int dis[maxn],head[maxn],dfn[maxn],low[maxn],st[maxn],vis[maxn],pos[maxn],a[maxn],w[maxn],ll[maxn];
    int n,m,top,sum,cnt,S,ind,p;
    
    void link(int u,int v) {
        e[++cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
    }
    void Tarjan(int x) {
        dfn[x]=low[x]=++ind;
        vis[x]=1;
        st[++top]=x;
        for (int i=head[x];i;i=e[i].next) {
            if (!vis[e[i].to]) {
                Tarjan(e[i].to);
                low[x]=min(low[x],low[e[i].to]);
            }
            else if (!pos[e[i].to])
                low[x]=min(low[x],dfn[e[i].to]);
        }
        if (dfn[x]==low[x]) {
            sum++;
            int j;
            do {
                j=st[top--];
                pos[j]=sum;w[sum]+=a[j];
            }while (st[top+1]!=x);
        }
    }
    void Dijkstra() {
        priority_queue<data> q;
        for (int i=1;i<=sum;i++) dis[i]=-inf;
        data y,x=(data){S,w[S]};
        q.push(x);dis[S]=w[S];
        while (q.size()) {
            x=q.top();q.pop();
            if (vis[x.num]) continue;
            vis[x.num]=1;
            for (int i=head[x.num];i;i=e[i].next)
                if (dis[e[i].to]<dis[x.num]+w[e[i].to]) {
                    dis[e[i].to]=y.x=dis[x.num]+w[e[i].to];
                    y.num=e[i].to;
                    q.push(y);
                }
        }
    }
    void SPFA() {
        queue<int> q;
        for (int i=1;i<=sum;i++) dis[i]=-inf;
        q.push(S);dis[S]=w[S];
        while (q.size()) {
            int x=q.front();q.pop();
            vis[x]=0;
            for (int i=head[x];i;i=e[i].next)
                if (dis[e[i].to]<dis[x]+w[e[i].to]) {
                    dis[e[i].to]=dis[x]+w[e[i].to];
                    if (!vis[e[i].to]) q.push(e[i].to);
                }
        }
    }
    int main() {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=m;i++) {
            scanf("%d%d",&ee[i].u,&ee[i].v);
            link(ee[i].u,ee[i].v);
        }
        for (int i=1;i<=n;i++) scanf("%d",&a[i]);
        scanf("%d%d",&S,&p);
        Tarjan(S);S=pos[S];
        for (int x,i=1;i<=p;i++) {
            scanf("%d",&x);
            ll[pos[x]]=1;
        }
        for (int i=1;i<=n;i++) vis[i]=head[i]=0;
        for (int i=1;i<=m;i++)
            if (pos[ee[i].u]!=pos[ee[i].v]) link(pos[ee[i].u],pos[ee[i].v]);
        //Dijkstra();   万万不可
        SPFA();
        int ans=0;
        for (int i=1;i<=sum;i++) if (ll[i]) ans=max(ans,dis[i]);
        printf("%d",ans);
        return 0;
    }
    

      

    This passage is made by MashiroSky.
  • 相关阅读:
    jvm内存模型学习
    sparkstreaming容错
    yum命里详解
    rpm包的安装及卸载
    git命令记录
    ElaticSearch基本查询
    入门elaticsearch
    Java网络编程学习(一)
    JAVA多线程之生产消费模型
    Java线程同步详解
  • 原文地址:https://www.cnblogs.com/MashiroSky/p/5914038.html
Copyright © 2011-2022 走看看