Evanyou Blog 彩带

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;
}

 

posted @ 2018-08-22 08:06  five20  阅读(324)  评论(0编辑  收藏  举报
Live2D