树和图的存储
1.树是一种特殊的图
2.图分为两种:有向图和无向图(无向图也是一种特殊的有向图)
3.有向图:
邻接矩阵,开个二维数组;
邻接表,每个点开一个单链表。
为每个点都开了一个单链表
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010;
int n,m;
int h[N], e[M],ne[M],idx;
bool st[N]; //宽度优先遍历和深度优先遍历每个点通常只遍历一次 用bool数组存储哪些点被遍历过了
void add(int a,int b)
{
ne[idx] = h[a], e[idx] = b, h[a] = idx++;
}
void dfs(int u)//树和图深搜
{
st[u] = true; //标记一下,已经被搜过了
for(int i=h[u], i!=-1; i=ne[i])
{
int j = e[i];
}
}
int main()
{
memset(h,-1,sizeof h);
dfs(1);
}
深度优先遍历:![](https://i-blog.csdnimg.cn/blog_migrate/cb455fae36871d29490b69540712e383.png)
#include <iostream>
#include <cstring>
using namespace std;
const int N = 100010, M=N*2;
int ans = N;
int n,m;
int h[N], e[M],ne[M],idx;
int st[N];
void add(int a,int b)
{
ne[idx] = h[a], e[idx] = b, h[a] = idx++;
}
int dfs(int u) //返回以u为根的子树中点的数量
{
st[u] = true;
int sum=1,res=0;
for(int i = h[u];i!=-1;i = ne[i]) //遍历所有出边
{
int j =e[i];
if(!st[j])
{
int s = dfs(j);
res = max(res,s);
sum+=s;
}
}
res = max(res,n-sum);
ans = min(ans,res);
return sum;
}
int main()
{
cin>>n;
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
dfs(1);
cout<<ans<<endl;
return 0;
}
宽度优先遍历:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100010;
int n,m;
int h[N], e[N], ne[N], idx;
int d[N], q[N];
void add(int a,int b)
{
ne[idx] = h[a], e[idx] = b, h[a] = idx++;
}
int bfs()
{
int hh=0,tt=0;
q[0] = 1; //用队列维护结点序号
memset(d, -1, sizeof d);
d[1] = 0;
while(hh<=tt)
{
int t = q[hh++]; //拿到队头序号
for(int i = h[t]; i!=-1;i = ne[i]) //遍历队头所有临边
{
int j = e[i]; //拿到指向的点的序号
if(d[j]==-1)
{
d[j] = d[t] +1;
q[++tt] = j;
}
}
}
return d[n];
}
int main()
{
cin>>n>>m;
memset(h, -1, sizeof h);
int a, b;
for(int i=0;i<m;i++)
{
cin>>a>>b;
add(a,b);
}
cout<<bfs()<<endl;
return 0;
}
有向无环图===拓扑序列
入度:所有指向它的边的数量
出度:所有指出去的边的数量
一个有向无环图,一定至少存在一个入度为0的点。
queue<------所有入度为0的点
while queue不空
{
t<------队头
枚举t 的所有出边t--->j
删掉t--->j, d[j]--;
if d[j] == 0;
queue<-----j;
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N= 100010;
int n,m;
int h[N], e[N], ne[N], idx;
int q[N], d[N]; //d[N]存的是每个点的入度
void add(int a,int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
bool topsort()
{
int hh=0,tt=-1;
for(int i=1;i<=n;i++)
{
if(!d[i])
q[++tt] = i;
}
while(hh<=tt)
{
int t = q[hh++];
for(int i=h[t];i!=-1;i=ne[i])
{
int j = e[i];
d[j]--;
if(d[j]==0) q[++tt] = j;
}
}
return tt==n-1;
}
int main()
{
cin>>n>>m;
memset(h, -1, sizeof h);
for(int i=0;i<m;i++)
{
int a,b;
cin>>a>>b;
add(a,b);
d[b]++;
}
if(topsort())
{
for(int i=0;i<n;i++) cout<<q[i]<<' ';
puts("");
}
else puts("-1");
return 0;
}