图的遍历(邻接表)

题目链接

https://www.luogu.com.cn/problem/P3916

先上题目(多多关注_qaq

题目描述

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

输入格式

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

输出格式

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.M≤10^3
• 对于100% 的数据,1≤N,M≤10^5

本人暴力枚举的时候,自己编译时,发现只有样例过了,自己编的数据一个都没过(内心有点酸~~~),后来才发现其实是邻接表。

邻接表

先引入一下邻接矩阵吧。!!!不是邻接表
对于一张图~~
在这里插入图片描述

我们可以先弄一张表格,如下:

0 1 1
1 0 0
1 0 0

其中,第i行第j列 表示 第i个城市和第j个城市是否联通(1为是,0为否)
由此,我们可得知 邻接矩阵具有对称性
————————————————————————————————————————
众所周知 邻接矩阵空间和时间复杂度都是N^2
让我们想一个问题:如果n为10^7呢?,那么将会有大量的空间被浪费。
————————————————————————————————————————

由此,神诞生了——邻接表~~~(此处省略巨多音效 )
简介:空间和时间复杂度就都是M。对于稀疏图来说,M要远远小于N^2。

扫描二维码关注公众号,回复: 12207924 查看本文章

假设有n个点,m条边

3 3
1 2
1 3
2 3

序号 head to next
2 2 0
3 3 1
0 3 0

可以发现,从第i点开始遍历,就先找到head[i]的序号,再找到to[head[i]](为此点可以到达的边的序号,接下来,i就变成next[head[i]]————(本人第一次做TLE了无数次_QAQ)
上机程序片段

for(int i=head[x];i;i=t[i].next)

请查阅 https://blog.csdn.net/vocaloid01/article/details/76576822

https://so.csdn.net/so/search/all?q=%E9%82%BB%E6%8E%A5%E8%A1%A8&t=all&p=1&s=0&tm=0&lv=-1&ft=0&l=&u=

主要思路

对于一个点j,只需要把与j链接的点i感染(ans)注意是逆序,就不用判断了——QAQ
如果有强迫症的话,就用 mmax[x]=max(mmax[x],u);

接下来就是 插入要反过来 便于感染

add(b,a);

然后从大的点i开始遍历,找到一个点z开始感染(附值)——。而如果有一个比点i小的点j,也找到了点z,那就直接跳过(因为i>j)节约时间——qaq

if(mmax[x])return;
mmax[x]=u;

在这里插入图片描述

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,m,a,b,x,y,c[100001],head[100001],mmax[100001],p;
struct abc{
    
    
	int to,next;
}t[100001];
void dfs(int x,int u){
    
    //深搜
    if(mmax[x])return;
	mmax[x]=u;//感染  mmax[x]=max(mmax[x],u);
	for(int i=head[x];i;i=t[i].next){
    
    
		dfs(t[i].to,u);
    }
}
void add(int a,int b){
    
    //插入
	p++;
	t[p].next=head[a];
	head[a]=p;
	t[p].to=b;
}
int main(){
    
    
	cin>>m>>n;
	for(int i=1;i<=n;i++){
    
    
	    cin>>a>>b;
	    add(b,a);
    }
    for(int u=m;u>=1;u--){
    
     重点:注意是逆向 后面就不用max()了————啊哈哈~
    	dfs(u,u); //第二个u是为了“感染”
	}
	for(int i=1;i<=m;i++)cout<<mmax[i]<<" ";
	//cout<<endl<<endl;
    //for(int i=1;i<=m;i++)printf("%3d. %3d %3d %3d\n",i,head[i],t[i].to,t[i].next);
}

~白白-QAQ

猜你喜欢

转载自blog.csdn.net/qq_46258139/article/details/112778596