ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

洛谷P3916

2019-06-09 16:38:43  阅读:205  来源: 互联网

标签:洛谷 int 样例 到达 P3916 cdots maxn dp


题目描述

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

输入输出格式

输入

第1行,2个整数\(N\),\(M\)。
接下来\(M\)行,每行2个整数U_i,V_i,表示边(U_i,V_i)。点用\(1,2,3\cdots N\)编号。

输出

\(N\)个整数\(\$A(1)\),\(A(2)\),\(\cdots,A(N)\)。

样例

输入样例

4 3
1 2
2 4
4 3

输出样例

4 4 3 4

思路

做这道题的方法不少。
在这里我只提一种
就是大法师(\(DFS\))。
可以采用反向建边,从最大的点开始\(DFS\)
我们考虑每次从所剩点中最大的一个点出发,我们暂且称它为\(i\),而凡是\(i\)这个点所能到达的点,可以到达的点最大都是\(i\)。
在遍历的时候按\(n\)——>\(1\)的顺序
因为是从大到小遍历,故每个点第一次被碰到的i一定是这个点最大可到达的点
上代码(走起)Music!!!

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int dfn[maxn],low[maxn],onStack[maxn],n,m,sum,res[maxn],cnt,scc[maxn],dp[maxn];
stack<int>s;
vector<int>e[maxn];
vector<int>new_e[maxn];
struct node{
    int x,y;
}edge[maxn];
void tarjan(int u){
    s.push(u);
    onStack[u]=true;
    dfn[u]=low[u]=++cnt;
    for(size_t i=0;i<e[u].size();i++){
        int next=e[u][i];
        if(dfn[next]==0){
            tarjan(next);
            low[u]=min(low[u],low[next]);
        }
        else if(onStack[next]==true)
            low[u]=min(low[u],low[next]);
    }
    if(dfn[u]==low[u]){
        sum++;
        onStack[u]=false;
        scc[u]=sum;
        res[sum]=max(res[sum],u);
        while(s.top()!=u){
            int cur=s.top();
            s.pop();
            onStack[cur]=false;
            scc[cur]=sum;
            res[sum]=max(res[sum],cur);
        }
        s.pop();
    }
}
inline void dfs(int x){
    if(dp[x]>0)
        return ;
    dp[x]=res[x];
    for(size_t i=0;i<new_e[x].size();i++){
        int next=new_e[x][i];
        if(dp[next]==0)
            dfs(next);
        dp[x]=max(dp[x],dp[next]);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1,u,v;i<=m;i++){
        scanf("%d%d",&u,&v);
        edge[i].x=u;
        edge[i].y=v;
        e[u].push_back(v);  
    }
    cnt=0;
    for(int i=1;i<=n;i++)
        if(dfn[i]==0)
            tarjan(i);
    for(int i=1;i<=m;i++){
        int xx=scc[edge[i].x];  
        int yy=scc[edge[i].y];
        if(xx!=yy)
            new_e[xx].push_back(yy);
        
    }
    for(int i=1;i<=sum;i++)
        if(dp[i]==0)
            dfs(i); 
    for(int i=1;i<=n;i++)
        printf("%d ",dp[scc[i]]);
    return 0;
}

标签:洛谷,int,样例,到达,P3916,cdots,maxn,dp
来源: https://www.cnblogs.com/xzj213/p/10993897.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有