• P3916 图的遍历


    题目描述

    给出 NNN 个点, MMM 条边的有向图,对于每个点 vvv ,求 A(v)A(v)A(v) 表示从点 vvv 出发,能到达的编号最大的点。

    输入输出格式

    输入格式:

    第1 行,2 个整数 N,MN,MN,M

    接下来 MMM 行,每行2个整数 Ui,ViU_i,V_iUi,Vi ,表示边 (Ui,Vi)(U_i,V_i)(Ui,Vi) 。点用 1,2,⋯,N1, 2,cdots,N1,2,,N 编号。

    输出格式:

    N 个整数 A(1),A(2),⋯,A(N)A(1),A(2),cdots,A(N)A(1),A(2),,A(N)

    输入输出样例

    输入样例#1: 
    4 3
    1 2
    2 4
    4 3
    输出样例#1: 
    4 4 3 4

    说明

    • 对于60% 的数据, 1≤N.K≤1031 le N . K le 10^31N.K103

    • 对于100% 的数据, 1≤N,M≤1051 le N , M le 10^51N,M105

    Solution:

      本题tarjan缩点+拓扑序dp(貌似大多数人直接dfs就过了?)。

      首先缩点,处理出每个连通分量并记录连通分量上的最大点值,然后重新建图得到一个DAG,这样就能愉快地跑一个简单的拓扑序dp出解了。

    代码:

    /*Code by 520 -- 8.21*/
    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    #define RE register
    #define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
    #define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
    using namespace std;
    const int N=2e5+7;
    struct node{
        int u,v;
    }e[N];
    int n,m,tot,dfn[N],low[N];
    int to[N],net[N],h[N],cnt;
    int stk[N],top;
    int f[N],ans;
    int scc,bl[N],val[N],rd[N];
    bool ins[N];
    
    int gi(){
        int a=0;char x=getchar();
        while(x<'0'||x>'9')x=getchar();
        while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+(x^48),x=getchar();
        return a;
    }
    
    il void add(int u,int v){to[++cnt]=v,net[cnt]=h[u],h[u]=cnt;}
    
    void tarjan(int u){
        dfn[u]=low[u]=++tot,stk[++top]=u,ins[u]=1;
        for(RE int i=h[u];i;i=net[i]){
            int v=to[i];
            if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
            else if(ins[v]) low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u]){
            scc++;
            while(stk[top+1]!=u)
                bl[stk[top]]=scc,val[scc]=max(val[scc],stk[top]),ins[stk[top--]]=0;
        }
    }
    
    queue<int>q;
    il void init(){
        n=gi(),m=gi();
        For(i,1,m) e[i].u=gi(),e[i].v=gi(),add(e[i].u,e[i].v);
        For(i,1,n) if(!dfn[i]) tarjan(i);
        memset(h,0,sizeof(h)),cnt=0;
        For(i,1,m) if(bl[e[i].u]!=bl[e[i].v]) add(bl[e[i].v],bl[e[i].u]),rd[bl[e[i].u]]++;
        For(i,1,scc) if(!rd[i]) q.push(i),f[i]=val[i];
        while(!q.empty()){
            int u=q.front();q.pop();
            for(RE int i=h[u];i;i=net[i]){
                f[to[i]]=max(f[to[i]],max(f[u],val[to[i]]));
                if(!(--rd[to[i]])) q.push(to[i]);
            }
        }
        For(i,1,n) printf("%d ",f[bl[i]]);
    }
    
    int main(){
        init();
        return 0;
    }
  • 相关阅读:
    nginx+vue刷新404
    java-Object类的解析(持续更新)
    Python源码学习(六)-PyCodeObject初探
    经典算法之不定方程问题
    MySql中的视图的概念及应用
    数据结构之 折半插入排序
    mahout算法源码分析之Itembased Collaborative Filtering实战
    【Android】为Android虚拟机创建SDCard
    30个酷毙的交互式网站(HTML5+CSS3)
    项目总结——也谈svn版本库迁移
  • 原文地址:https://www.cnblogs.com/five20/p/9515536.html
Copyright © 2020-2023  润新知