ATM(BZOJ 1179)

测评传送门

题意:

给你一个有向无环图,每个点有一个权值,给定起点,和多个终点。

求到达终点的最大权值。

输入

6 7 
1 2 
2 3 
3 5 
2 4 
4 1 
2 6 
6 5 
10 12 8 16 1 5 
1 4 
4 3 5 6 

输出

47 

 


思路:

Tarjan 缩点,点权转边权,跑SPFA

感谢nan葛格的博客讲解

code

#include<stdio.h> 
#include<stack>
#include<queue>
#include<algorithm> 
using namespace std;
const int mxn=510000;
struct Edge {
    int to,next;
}e[mxn<<1],E[mxn<<1];
int n,m,cnt,idx,tot,st,k,ans;
int first[mxn<<1],dfn[mxn],low[mxn],w[mxn],W[mxn],bel[mxn],dis[mxn],head[mxn<<1];
bool ins[mxn],vis[mxn];
stack<int> stk;
queue<int> q;
void add(int from,int to) {
    e[++cnt].to=to;
    e[cnt].next=first[from];
    first[from]=cnt;
}

void Tarjan(int x) 
{
    dfn[x]=low[x]=++idx;
    ins[x]=1;stk.push(x);
    for(int i=first[x];i;i=e[i].next) {
        int to=e[i].to;
        if(!dfn[to]) {
            Tarjan(to);
            low[x]=min(low[x],low[to]);
        } 
        else if(ins[to]) low[x]=min(low[x],dfn[to]);
     }
    if(low[x]==dfn[x]) {
        tot++;
        int top;
        do {
            top=stk.top();stk.pop();
            ins[top]=0;
            bel[top]=tot;
        }while(top!=x);
    }
}

void rebuild() 
{ 
    for(int x=1;x<=n;++x) {
        for(int i=first[x];i;i=e[i].next) {
            int to=e[i].to;
            if(bel[x]==bel[to]) continue;
            E[++cnt].to=bel[to];
            E[cnt].next=head[bel[x]];
            head[bel[x]]=cnt;
        }
        W[bel[x]]+=w[x];
    }
}

void spfa() 
{
    dis[bel[st]]=W[bel[st]];
    q.push(bel[st]);
    while(!q.empty()) {
        int x=q.front();q.pop();
        vis[x]=0;
        for(int i=head[x];i;i=E[i].next) 
        {
            int to=E[i].to;
            if(dis[x]+W[to]>dis[to]) {
                dis[to]=dis[x]+W[to];
                if(!vis[to]) {
                    vis[to]=1;
                    q.push(to);
                }
            }
        }
    }
}
   
int main() 
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i) {
        int from,to;    
        scanf("%d%d",&from,&to);
        add(from,to);
    }
    for(int i=1;i<=n;++i) {
        scanf("%d",&w[i]);
        if(!dfn[i]) Tarjan(i);
    }
    cnt=0;
    rebuild();
    scanf("%d%d",&st,&k);
    spfa();
    for(int i=1;i<=k;++i) {
        int x;
        scanf("%d",&x);
        ans=max(ans,dis[bel[x]]);
    }
    printf("%d",ans);
    return 0;
}
/*
6 7 
1 2 
2 3 
3 5 
2 4 
4 1 
2 6 
6 5 
10 12 8 16 1 5 
1 4 
4 3 5 6 
*/
原文地址:https://www.cnblogs.com/qseer/p/9831711.html