一:深度遍历:
1.邻接矩阵:
int a[1000][1000];//图
int flag[1000];
int n,m;//n,m分别为行列
void dfs(int st)
{
for(int i=st;i<=m;i++)
{
if(a[st][j]==1&&!flag[i])
{
flag[i]=1;
dfs(i);
}
}
}
2.邻接表:
void insert(int x,int y)
{
e[idx]=y,ne[idx]=h[x],h[x]=idx++;
}
void dfs(int st)
{
flag[st]=1;//为什么要先标记此节点,因为递归时遍历的都是其指向的节点,若放入判断后则需事先标记递归起点
for(int i=h[st];i!=-1;i=ne[i])
{
int j=e[i];
if(!flag[j])
dfs(j);
}
}
二:广度遍历:
拓扑排序:
三:最短路
1.dijkstra堆优化(稀疏图)
堆优化总原理:将起点入队,初次循环,循环中选定离起点最近的节点t,在上步之前标记t,flag[t]=1(即将属于到已经找到最短距离节点的集合),然后用t来更新和t相邻节点j中的边dist[j],也就是松弛操作。将所有松弛操作后的相邻节点j入队(小根堆)。再次循环,取队列中距离最近的节点。判断若此节点已标记过则直接进行下次循环(跳过此节点的松弛操作)。持续循环直到队列中没有元素,即找到了起点到所有节点的最短路。
总结:贪心原理,每次找离集合flag最近的节点t,将t出队,利用t来松弛它的临边后,将临边和其临边终点的值都入队,一直循环直到队列为空。
typedef pair<int,int> PII;
priority_queue< PII,vector<PII>,greater<PII> > que;
void add(int a,int b,int l)
{
e[idx]=b;ne[idx]=h[a],w[idx]=l,h[a]=idx++;
}
void dijkstra(int k)
{
for(int i=1;i<=n;i++)
dist[i]=INF;
dist[k]=0;
que.push({0,k});
while(!que.empty())
{
int t=que.top().second;
que.pop();
if(flag[t]) continue;
flag[t]=1;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
que.push({dist[j],j});
}
}
}
for(int i=1;i<=n;i++)
printf("%d ",dist[i]);
}
2.spfa(稠密图,稀疏图,支持负边权,判断负环)
spfa利用普通队列,每次用队首节点t去松弛它的所有临边。并将其临边终点节点入队(若队中已有则不入),继续循环直到队列为空。
void spfa(int k)//求节点k到各个节点的最短距离
{
for(int i=1;i<=n;i++)
dist[i]=INF;
dist[k]=0;
que.push(k);
flag[k]=1;
while(!que.empty())
{
int t=que.front();
flag[t]=0;
que.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(dist[j]>dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
if(!flag[j])
{
que.push(j);
flag[j]=1;
}
}
}
}
for(int i=1;i<=n;i++)
printf("%d ",dist[i]);
}
3.floyd(多源最短路)
floyd求最短路不需要dist数组,但注意插入边时一定一定要判重边!!!!
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
a[i][j]=min(a[i][j],a[i][k]+a[k][j]);
}
}
void int()//初始化
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i==j)
a[i][j]=0;
else
a[i][j]=INF;
}
}