缩点

这个就是最基本的了.

主要是用来造出DAG然后跑个topo之类的DP

#include <bits/stdc++.h>
#define mod 23333
#define ll long long
#define F(i,i0,n) for(int i=i0;i<=n;i++)
#define N 600005
#define M 1000005
using namespace std;
inline int rd(){
    int x=0,f=1;char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
    return x*f;
}
int p[M],id;
struct edge{
    int u,v,nt;
}e[M];

void add(int x,int y){
    e[++id]={x,y,p[x]};
    p[x]=id;
}
int n,m,a[N],dfn[N],low[N],st[N],top,num,co[N],val[N],col;
void Tanjan(int u){
    dfn[u]=low[u]=++num;
    st[++top]=u;
    for(int i=p[u];i;i=e[i].nt){
        int v=e[i].v;
        if(!dfn[v]){
            Tanjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!co[v]){
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(low[u]==dfn[u]){
        co[u]=++col;
        val[col]+=a[u];
        while(st[top]!=u){
            co[st[top]]=col;
            val[col]+=a[st[top]];
            --top;
        }
        --top;
    }
}
int d[N],s[N];
int main() {
    n=rd(),m=rd();
    F(i,1,n)a[i]=rd();
    F(i,1,m){
        int x=rd(),y=rd();
        add(x,y);
    }   
    for(int i=1;i<=n;i++){
        if(!dfn[i])Tanjan(i);
    }
    memset(p,0,sizeof(p));
    id=0;
    for(int i=1;i<=m;i++){
        int u=e[i].u,v=e[i].v;
        if(co[u]!=co[v]){
            add(co[u],co[v]);
            d[co[v]]++;
        }
    }
    queue<int>q;
    for(int i=1;i<=col;i++){
        if(!d[i])q.push(i),s[i]=val[i];
    }
    int ans=0;
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=p[u];i;i=e[i].nt){
            int v=e[i].v;
            s[v]=max(s[v],s[u]+val[v]);
            if(--d[v]==0)q.push(v);
        }
        ans=max(ans,s[u]);
    }
    cout<<ans<<endl;
    return 0;
}
posted @ 2023-09-09 17:07  ussumer  阅读(26)  评论(0)    收藏  举报