-
题目是洛谷5518
-
拿到题目我就知道我不会做,于是赶紧看看题解。 -
首先是图的存储,一般来说,图的存储使用两种方法:
-
- 邻接表:
有点复杂,我就没看
- 邻接表:
-
- 邻接矩阵:非常简单好理解,就是个二维数组
- 邻接矩阵:非常简单好理解,就是个二维数组
-
二是dfs 递归思想,相对简单
-
三是bfs 这一步要用到 队列
-
虽然数据结构早就学过了,没办法辣鸡的我不会,又去学队列
大佬关于队列的博客
于是我写出了第一版代码
#include<iostream>
using namespace std;
const int N=1e5+10;
int wx[1001][1001],flag1[1001]={0},flag2[1001]={0},q[1001]={0};
int n,m;
void clear(int n) {
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
wx[i][j]=0;
}
void dfs(int node)
{
cout<<node<<" ";
flag1[node]=1;
for(int i=1;i<=n;i++)
{
if(wx[node][i]==1&&flag1[i]==0)
dfs(i);
}
return ;
}
void bfs(int node)
{
int head=0,tail=1;
q[head]=node;
flag2[node]=1;
cout<<node<<" ";
while(tail>head)
{
for(int i=1;i<=n;i++)
{
if(wx[node][i]==1&&flag2[i]==0)
{
q[tail]=i;
tail++;
flag2[i]=1;
cout<<i<<" ";
}
}
node=q[head++];
}
}
int main()
{
cin>>n>>m;
clear(n);
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
wx[a][b]=1;
}
dfs(1);
cout<<endl;
bfs(1);
return 0;
}
- 此时我已经过了样例,不过我早就知道,我的数据范围太小,不可能AC。本题数据范围是1e5,明显二维数组不可行。为什么我会知道呢(
因为我看题解了啊) - 那没办法我还要继续
看题解学习。 - 既然邻接矩阵不行,就只能用邻接表喽
- 所以开始学习邻接表,看到题解中的大佬们写的用 or 等看不懂的东西,我果断百度了一下,
好神奇呢我还是看不懂呢,于是我果断放弃,转而去看实验室讲图论的大佬的ppt
- 看起来挺简单的不过不还是二维数组存N吗?数组应该还是会爆吧,但是本着学习的念头我还是要写出来试试。(
因为这个也不会)
于是写出的第二版代码如下
#include<iostream>
using namespace std;
const int N=1e5+10;
int wx[1001][1001],flag1[1001]={0},flag2[1001]={0},q[1001]={0};
int n,m;
//struct wenxian{
// int last;
// int next;
// //int node;
//}wx[N];
void clear(int n) {
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
wx[i][j]=0;
}
void dfs(int node)
{
cout<<node<<" ";
flag1[node]=1;
for(int i=1;i<=wx[node][0];i++)
{
if(flag1[wx[node][i]]==0)
dfs(wx[node][i]);
}
return ;
}
void bfs(int node)
{
cout<<node<<" ";
int head=0,tail=1;
q[head]=node;
flag2[node]=1;
while(head<tail)
{
for(int i=1;i<=wx[node][0];i++)
{
if(flag2[wx[node][i]]==0)
{
flag2[wx[node][i]]=1;
q[tail]=wx[node][i];
tail++;
cout<<wx[node][i]<<" ";
}
}
node=q[head++];
}
}
int main()
{
cin>>n>>m;
clear(n);
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
wx[a][0]++;
wx[a][wx[a][0]]=b;
}
dfs(1);
cout<<endl;
bfs(1);
return 0;
}
- 但我在写的过程中发现一个严重的问题,题目要求遍历过程从小到大排序,但似乎sort函数无法实现二维数组的排序?其他排序肯定巨麻烦,而且我也知道这个二位数组在N下会爆,所以开始看大佬写的ppt的下一个方法。
- 方法二是一个结构体,
我觉得这个方法存应该就对了,毕竟看起来就和题解中的好像
![在这里插入图片描述](https://img-blog.csdnimg.cn/2021042120042
- 看了一会感觉这个方法似乎和之前看过的xx向前*有异曲同工之妙,head[]记录的是每个开始点到最后结束点的边的序号。
- 最后我写出了它的储存图的代码,但是问题是这种方法是倒着存的,对于有向图无论是bfs还是dfs都不知道咋写,我也没查到相关的,况且题目要求排序,这我就更不会了。那只能先放弃这个了,我果断决定下一步要直接看题解。
(大无语事件)找到一个和刚才方法相似的题解,理解了两个小时写出了一个代码,然后发现自己刚才学的那个结构体其实是完全可以dfs的,只不过我的dfs写错了……而且其实那个方法比题解还简单……- 但是写都写了不能浪费,我先写完看看吧。结果哭死孩子,只会写dfs,bfs写不出来……
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int head[N]={0},next[N]={0},flag1[1001]={0},flag2[1001]={0},q[1001]={0},num=0;
int n,m;
struct www{
int from,toto;
}ww[N];
bool cmp(www a,www b){
if(a.from!=b.from)
return a.from>b.from;
return a.toto>b.toto;
}
void clear() {
for(int i=0;i<N;i++)
{
ww[i].from=0;
ww[i].toto=0;
head[i]=0;
}
}
void add_wx(int a,int b)
{
next[++num]=head[a];
head[a]=num;
}
void dfs(int node)
{
cout<<node<<" ";
flag1[node]=1;
while(head[node])
{
if(flag1[ww[head[node]].toto]==0)
{
dfs(ww[head[node]].toto);
}
head[node]=next[head[node]];
}
return ;
}
int main()
{
cin>>n>>m;
clear();
for(int i=1;i<=m;i++)
{
int a,b;
cin>>ww[i].from>>ww[i].toto;
}
sort(ww+1,ww+m+1,cmp);
for(int i=1;i<=m;i++)
add_wx(ww[i].from,ww[i].toto);
dfs(1);
cout<<endl;
// bfs(1);
return 0;
}
- 我知道为啥bfs出不来了,代码没有啥大错,但是head数组在dfs时被全部清空了……小垃圾不会别的,于是只好把head复制一个为hhead,让他来bfs。
- 最后的最后,还是过了,不说了上代码
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e6+10;
int head[N]={0},hhead[N]={0},next[N]={0},flag1[N]={0},flag2[N]={0},q[N]={0},num=0;
int n,m;
struct www{
int from,toto;
}ww[N];
bool cmp(www a,www b){
if(a.from!=b.from)
return a.from>b.from;
return a.toto>b.toto;
}
void clear() {
for(int i=0;i<N;i++)
{
ww[i].from=0;
ww[i].toto=0;
head[i]=0;
}
}
void add_wx(int a,int b)
{
next[++num]=head[a];
head[a]=num;
}
void dfs(int node)
{
cout<<node<<" ";
flag1[node]=1;
while(head[node])
{
if(flag1[ww[head[node]].toto]==0)
{
dfs(ww[head[node]].toto);
}
head[node]=next[head[node]];
}
return ;
}
void bfs(int node)
{
cout<<node<<" ";
int head1=0,tail=1;
q[head1]=node;
flag2[node]=1;
while(head1<tail)
{
for(int i=hhead[node];i;i=next[i])
// while(hhead[node]!=0||)
{
//int i=hhead[node];
if(flag2[ww[i].toto]==0)
{
flag2[ww[i].toto]=1;
q[tail]=ww[i].toto;
tail++;
cout<<ww[i].toto<<" ";
hhead[node]=next[hhead[node]];
}
}
node=q[head1++];
}
}
int main()
{
cin>>n>>m;
clear();
for(int i=1;i<=m;i++)
{
int a,b;
cin>>ww[i].from>>ww[i].toto;
}
sort(ww+1,ww+m+1,cmp);
for(int i=1;i<=m;i++)
add_wx(ww[i].from,ww[i].toto);
for(int j=0;j<=N;j++)
hhead[j]=head[j];
dfs(1);
cout<<endl;
bfs(1);
return 0;
}
- 有一点我还不是太清楚,就是
- for(int i=hhead[node];i;i=next[i])
- 题解里大佬这么写的,我也是头一次看到……因为我写的循环条件有问题,但我不知道哪有问题……而且也不会改……