zoukankan      html  css  js  c++  java
  • 强连通缩点+拓扑图上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]]<<'
    ';
        
    }
  • 相关阅读:
    nginx 开机自动启动
    Linux 常用命令
    php中数组操作函数
    Windows系统下GitBash显示的中文乱码解决方案
    更改Git默认编辑器为notepad++
    【js】函数问题
    【JS】JavaScript中的参数传递
    Android基础整理之四大组件Activity
    关于BaseAdapter的使用及优化心得(一)
    使用MySQL Workbench建立数据库,建立新的表,向表中添加数据
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12300379.html
Copyright © 2011-2022 走看看