bzoj 1179 tarjan+spfa

  首先我们可以将这个图缩成DAG,那么问题中的路线就可以简化为DAG中的一条链,那么我们直接做一遍spfa就好了。

  反思:开始写的bfs,结果bfs的时候没有更新最大值,而是直接赋的值,后来发现不能写bfs,因为每个点可能进队好多次,当让可以改成循环队列什么的bfs,然后我就改成了spfa,伪的spfa,就是判一下这个点是不是更优了,更优才入队。

/**************************************************************

    Problem: 1179

    User: BLADEVIL

    Language: C++

    Result: Accepted

    Time:6640 ms

    Memory:109356 kb

****************************************************************/

 

//By BLADEVIL

#include <cstdio>

#include <cstring>

#include <algorithm>

#define maxm 2000010

#define maxn 2000010

 

using namespace std;

 

int n,m,s,tot,time,num,p,l;

int pre[maxm],other[maxm],last[maxn],key[maxn],flag[maxn];

int stack[maxn],dfn[maxn],low[maxn],vis[maxn],col[maxn],que[maxn],w[maxn];

 

void connect(int x,int y) {

    pre[++l]=last[x];

    last[x]=l;

    other[l]=y;

}

 

void dfs(int x) {

    stack[++tot]=x; vis[x]=1;

    dfn[x]=low[x]=++time;

    for (int p=last[x];p;p=pre[p]) {

        if (!dfn[other[p]]) 

            dfs(other[p]),low[x]=min(low[x],low[other[p]]); else

        if (vis[other[p]]) low[x]=min(low[x],dfn[other[p]]);

    }

    if (dfn[x]==low[x]) {

        int cur=-1;

        num++;

        while (cur!=x) {

            cur=stack[tot--];

            vis[cur]=0;

            col[cur]=num;

        }

    }

}

 

int main() {

    scanf("%d%d",&n,&m); num=n;

    for (int i=1;i<=m;i++) {

        int x,y; scanf("%d%d",&x,&y);

        connect(x,y);

    }

    for (int i=1;i<=n;i++) scanf("%d",&key[i]);

    scanf("%d%d",&s,&p);

    while (p--) {

        int x; scanf("%d",&x);

        flag[x]=1;

    }

    dfs(s);

    for (int i=1;i<=n;i++) {

        for (int p=last[i];p;p=pre[p]) if (col[i]!=col[other[p]]) connect(col[i],col[other[p]]);

    }

    for (int i=1;i<=n;i++) key[col[i]]+=key[i],flag[col[i]]|=flag[i];

    memset(vis,0,sizeof vis);

    que[1]=col[s]; vis[col[s]]=1; w[col[s]]=key[col[s]];

    int h=0,t=1,ans=0;

    while (h<t) {

        int cur=que[++h];

        if (flag[cur]) ans=max(ans,w[cur]);

        for (int p=last[cur];p;p=pre[p]) {

            if (w[cur]+key[other[p]]>w[other[p]]) {

            w[other[p]]=max(w[other[p]],w[cur]+key[other[p]]);

            que[++t]=other[p]; vis[other[p]]=1;

            }

        }

    }

    printf("%d\n",ans);

    return 0;

}

 

你可能感兴趣的:(SPFA)