强连通缩点+拓扑图上dp——cf894E

/*
强连通缩点后得到一个拓扑图
把这个拓扑图取反,在图上进行dp,最后dp[s]就是答案 
*/
#include<bits/stdc++.h>
using namespace std;
#define N 2000006
#define ll long long 

struct Edge{
    ll to,w,nxt;
}e[N<<1],e_n[N<<1]; 
int n,m,head[N],tot,head_n[N],tot_n;
void init(){
    memset(head,-1,sizeof head);
    memset(head_n,-1,sizeof head_n);
    tot=tot_n=0;
}
void add(int u,int v,ll w){
    e[tot].w=w; e[tot].to=v;
    e[tot].nxt=head[u]; head[u]=tot++;
}
void add_n(int u,int v,ll w){
    e_n[tot_n].w=w; e_n[tot_n].to=v;
    e_n[tot_n].nxt=head_n[u]; head_n[u]=tot_n++;
}

ll F[N];
vector<int>scc[N];
int c[N],cnt,low[N],dfn[N],ins[N],stk[N],ind,top;
void tarjan(int x){
    low[x]=dfn[x]=++ind;
    ins[x]=1;stk[++top]=x;
    for(int i=head[x];i!=-1;i=e[i].nxt){
        int y=e[i].to;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(ins[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x]){
        cnt++;int y;
        do{
            y=stk[top--];
            scc[cnt].push_back(y);
            c[y]=cnt;ins[y]=0;
        }while(y!=x);
    }
}

ll val[N],dp[N];
int in[N],vis[N];
inline ll calc(ll x){
    ll L=0,R=1e8,mid,ans;
    while(L<=R){
        mid=L+R>>1;
        if(mid*(mid+1)/2<=x)
            ans=mid,L=mid+1;
        else R=mid-1;
    }
    return x*(ans+1)-F[ans];
}

int main(){
    init();
    for(int i=1;i<=1000000;i++)F[i]=i;
    for(int i=1;i<=1000000;i++)F[i]+=F[i-1];
    for(int i=1;i<=1000000;i++)F[i]+=F[i-1];
    
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        ll u,v,w;scanf("%lld%lld%lld",&u,&v,&w);
        add(u,v,w);
    }
    //缩点 
    for(int i=1;i<=n;i++)
        if(!dfn[i])tarjan(i);
    //建立新图 
    for(int u=1;u<=n;u++)
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int v=e[i].to;
            if(c[u]==c[v])
                val[c[u]]+=calc(e[i].w);        
            else{
                add_n(c[v],c[u],e[i].w);//建的是反图 
                in[c[u]]++;
            }
        }
    
    queue<int>q;
    for(int i=1;i<=cnt;i++)
        if(in[i]==0){
            q.push(i);vis[i]=1;dp[i]=val[i];
        }
    while(q.size()){
        int u=q.front();q.pop();
        for(int i=head_n[u];i!=-1;i=e_n[i].nxt){
            int v=e_n[i].to;
            if(vis[v])continue;
            dp[v]=max(dp[v],dp[u]+e_n[i].w);
            in[v]--;
            if(in[v]==0){
                q.push(v);
                dp[v]+=val[v];
                vis[v]=1;
            }
        }
    }
    
    int s;cin>>s;
    cout<<dp[c[s]]<<'\n';
    
}

 

posted on 2020-02-12 19:06  zsben  阅读(167)  评论(0编辑  收藏  举报

导航