zoukankan      html  css  js  c++  java
  • tarjan 求缩点

    给定一个 nn 个点 mm 条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。

    允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。

    第一行两个正整数 n,mn,m

    第二行 nn 个整数,依次代表点权

    第三至 m+2m+2 行,每行两个整数 u,vu,v,表示一条 u ightarrow vuv 的有向边。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=10005;
    ll n,m,sum,tim,top,s;
    ll p[maxn],head[maxn],sd[maxn],dfn[maxn],low[maxn];
    ll stac[maxn],vis[maxn];
    ll h[maxn],in[maxn],dist[maxn];
    struct st {
        int to;
        int next;
        int from;
    }edge[maxn*10],ed[maxn*10];
    void add(int x,int y){
        edge[++sum].next=head[x];
        edge[sum].from=x;
        edge[sum].to=y;
        head[x]=sum;
    }
    void tarjan(int x){
        low[x]=dfn[x]=++tim;
        stac[++top]=x;
        vis[x]=1;
        for(int i=head[x];i;i=edge[i].next){
            int v=edge[i].to;
            if(!dfn[v]){
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else if(vis[v]){
                low[x]=min(low[x],low[v]);    
            }
        }
        if(dfn[x]==low[x]){
            int y;
            while(y=stac[top--]){
                sd[y]=x;
                vis[y]=0;
                if(x==y){
                    break;
                }
                p[x]+=p[y];
            }
        }
    }
    ll topo(){
        queue<int >q;
        int tot=0;
        for(int i=1;i<=n;i++){
            if(sd[i]==i&&!in[i]){
                q.push(i);
                dist[i]=p[i];
            }
        }
        while(!q.empty()){
            int temp=q.front();
            q.pop();
            for(int i=h[temp];i;i=ed[i].next){
                int v=ed[i].to;
                dist[v]=max(dist[v],dist[temp]+p[v]);
                in[v]--;
                if(in[v]==0)q.push(v);
            }
        }
        ll ans=0;
        for(int i=1;i<=n;i++){
            ans=max(ans,dist[i]);
        }
        return ans;
    }
    void solve(){
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>p[i];
        for(int i=1;i<=m;i++){
            ll u,v;
            cin>>u>>v;
            add(u,v);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
                tarjan(i);
            }
        }
        for(int i=1;i<=m;i++){
            int x=sd[edge[i].from],y=sd[edge[i].to];
            if(x!=y){
                ed[++s].next=h[x];
                ed[s].to=y;
                ed[s].from=x;
                h[x]=s;
                in[y]++;
            }
        }
        cout<<topo()<<endl;
    }
    int main(){
        ios::sync_with_stdio(false);cin.tie(0);
    //    freopen("1.in","r",stdin);
    //    getlist(1e7);
        int t=1;
        //cin>>t;
        while(t--){
            solve();
        }
        
    }
    rush!
  • 相关阅读:
    Accoridion折叠面板
    mui列表系列
    按照中文首字母排序查询表数据
    五分位算法
    springmvc添加拦截器
    springmvc添加定时任务
    通过后台解决跨域调用接口问题
    eclipse搭建ssm框架
    Java 将图片转成base64,传到前台展示
    用mysql存储过程代替递归查询
  • 原文地址:https://www.cnblogs.com/LH2000/p/14823879.html
Copyright © 2011-2022 走看看