【缩点】洛谷P3387

SPFA的tarjan缩点 是真的慢很多 但是也是真的很好理解

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=100010;
bool vis[maxn];
int n,m,ans=0,cnt=0,tot=0,top=0,num=0;
int u[maxn],v[maxn],head[maxn],low[maxn],dfn[maxn];
int dis[maxn],Dis[maxn],stack[maxn],po[maxn],a[maxn];
struct Edge{
    int next,to;
}cute[maxn];

void build(int x,int y)
{
    cute[++tot].next=head[x];
    cute[tot].to=y;
    head[x]=tot;
} 

void tarjan(int x)
{
    dfn[x]=low[x]=++num;
    stack[++top]=x;
    vis[x]=true;
    for(int i=head[x];i;i=cute[i].next)
    {
        int y=cute[i].to;
        if(vis[y]) low[x]=min(low[x],dfn[y]);
        else if(!dfn[y]) tarjan(y),low[x]=min(low[x],low[y]);
    }
    if(low[x]==dfn[x])
    {
        vis[x]=false;
        cnt++;
        while(stack[top+1]!=x)
        {
            po[stack[top]]=cnt;
            vis[stack[top]]=false;
            Dis[cnt]+=a[stack[top]];
            top--;
        }
    }
}

void Spfa(int x)
{
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    dis[x]=Dis[x];
    queue<int> q;
    vis[x]=true;
    q.push(x);
    while(!q.empty())
    {
        int u=q.front();
        vis[u]=false;
        q.pop();
        for(int i=head[u];i;i=cute[i].next)
        {
            int v=cute[i].to;
            if(dis[v]<dis[u]+Dis[v])
            {
                dis[v]=dis[u]+Dis[v];
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(v); 
                }
            }
        }
    }
    for(int i=1;i<=n;i++) ans=max(ans,dis[i]); 
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&u[i],&v[i]);
        build(u[i],v[i]);//有向图 建一次边
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i);
    memset(head,0,sizeof(head));
    memset(cute,0,sizeof(cute));
    for(int i=1;i<=m;i++)
        if(po[u[i]]!=po[v[i]]) build(po[u[i]],po[v[i]]);
    for(int i=1;i<=n;i++) Spfa(i);
    printf("%d",ans);
    return 0;
}

 

posted @ 2018-10-30 21:49  Koiny  阅读(87)  评论(0编辑  收藏  举报