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;
}

 

posted on 2014-04-07 19:30  BLADEVIL  阅读(338)  评论(0编辑  收藏  举报