救救孩子吧,ACon2,6,8,10
查看原帖
救救孩子吧,ACon2,6,8,10
534430
amxxxxx楼主2022/12/21 19:56
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],low[N],dfn[N],ti=0;
//in数组记录入度 sec数组记录新图
int in[N],sec[N];
int vis[N];
//手写栈
int s[N],top=0;
int cnt=0,head[N],head2[N];
struct node{
    int u,v,nxt;
    node(){u=v=0;}
}edge[N],edge2[N];
inline int read(){
    int x=0;
    bool f=true;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar())
        if(ch=='-')f=false;
    for(;isdigit(ch);ch=getchar())
        x=(x<<1)+(x<<3)+ch-'0';
    return f?x:~(x-1);
}
inline void add(int u,int v){
    edge[++cnt].u=u;
    edge[cnt].v=v;
    edge[cnt].nxt=head[u];
    head[u]=cnt;
}
inline void add2(int u,int v){
    edge2[++cnt].u=u;
    edge2[cnt].v=v;
    edge2[cnt].nxt=head2[u];
    head2[u]=cnt;
    in[v]++;
}
//求强连通分量
void dfs(int k){
    s[++top]=k;
    vis[k]=1;
    //ti为时间戳
    dfn[k]=++ti,low[k]=ti;
    for(int i=head[k];i;i=edge[i].nxt){
        int v=edge[i].v;
        //没搜索过
        if(dfn[v]==0){
            dfs(v);
            low[k]=min(low[k],low[v]);
        }else if(vis[v])low[k]=min(low[k],dfn[v]);
    }
    //当前点是强连通分量的第一个起点
    //即已经找到一个强连通分量
    if(dfn[k]==low[k]){
        int x;
        while(x=s[top--]){
            //k即为当前强连通分量合并后的节点编号
            sec[x]=k;
            vis[x]=0;
            if(x==k)break;
            a[k]+=a[x];
        }
    }
}
//DAG DP求最大值
int toupu(){
    queue<int>q;
    int ans[N],sum=0;
    for(int i=1;i<=n;i++){
        if(sec[i]==i&&!in[i]){
            q.push(i);
            ans[i]=a[i];
        }
    }
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head2[u];i;i=edge2[i].nxt){
            int v=edge2[i].v;
            ans[v]=max(ans[v],ans[u]+a[v]);
            if(--in[v]==0)q.push(v);
        }
    }
    for(int i=1;i<=n;i++){
        sum=max(sum,a[i]);
    }
    return sum;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        a[i]=read();
    }
    for(int i=1;i<=m;i++){
        int u=read(),v=read();
        add(u,v);
    }
    for(int i=1;i<=n;i++){
        if(dfn[i]==0)
            dfs(i);
    }
    cnt=0;
    for(int i=1;i<=m;i++){
        int u=sec[edge[i].u],v=sec[edge[i].v];
        if(u!=v)add2(u,v);
    }
    int ans=toupu();
    printf("%d\n",ans);
    return 0;
}

2022/12/21 19:56
加载中...