洛谷P3916 圖的遍歷 [圖論,搜索]


  題目傳送門

圖的遍歷

題目描述

給出 N 個點, M條邊的有向圖,對於每個點 v ,求 A(v) 表示從點 v 出發,能到達的編號最大的點。

輸入輸出格式

輸入格式:

 

第1 行,2 個整數 N,M 。

接下來 M行,每行2個整數 Ui,Vi ,表示邊 (Ui,Vi) 。點用 1,2,,N 編號。

 

輸出格式:

 

N 個整數 A(1),A(2),,A(N) 。

 

輸入輸出樣例

輸入樣例#1: 復制
4 3
1 2
2 4
4 3
輸出樣例#1: 復制
4 4 3 4

說明

• 對於60% 的數據,1N.K103 ;

• 對於100% 的數據,1N,M105 。

 


 

分析:

  一開始看到這題想到的還是Tarjan縮點+dfs,但是還有更加巧妙的方法可以更簡便地AC。

  首先分析,直接搜索肯定是有錯誤的,因為會有環,如果數據故意卡的話是很容易卡死的(因為遍歷順序是與存邊順序有關的,而且又是有向圖,直接搜可能會導致WA掉)

  當然環可以縮點去掉。但是這樣太麻煩了,不如換個思路。

  因為要求的是可以到達的編號最大的點,那么我們可以反向建邊,問題就轉換為求可以到達該點的最大編號的點,那么就從n到1反向遍歷,直接一邊dfs即可。當然要注意,該圖不一定是個連通圖。具體看代碼。

  Code:

 

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int n,m,head[N],size,ans[N];
struct Node{int to,next;}edge[N];
inline int read()
{
    char ch=getchar();int num=0;bool flag=false;
    while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
    while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
    return flag?-num:num;
}
inline void add(int x,int y)
{
    edge[++size].to=y;
    edge[size].next=head[x];
    head[x]=size;
}
inline void dfs(int u,int sum)
{
    if(ans[u])return;
    ans[u]=sum;
    for(int i=head[u];i!=-1;i=edge[i].next){
    dfs(edge[i].to,sum);}
}
int main()
{
    n=read();m=read();int x,y;
    memset(head,-1,sizeof(head));
    memset(ans,0,sizeof(ans));
    for(int i=1;i<=m;i++){
    x=read();y=read();add(y,x);}
    for(int i=n;i>=1;i--)
    if(!ans[i])dfs(i,i);
    for(int i=1;i<=n;i++)
    printf("%d ",ans[i]);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM