码迷,mamicode.com
首页 > 其他好文 > 详细

图论常见解题方法和套路

时间:2020-07-24 21:22:49      阅读:84      评论:0      收藏:0      [点我收藏+]

标签:class   结构   启发式   code   top   second   line   spfa   get   

一、Dijkstra和spfa

以下示例均使用邻接表。
Dijkstra:

void Dijkstra(int S)
{
	priority_queue <pii> Q;
  
	while(!Q.empty()) Q.pop();
        memset(dis, 0x7f, sizeof(dis);
        memset(vis, false, sizeof(vis));
	Q.push(make_pair(0, S));
	dis[S] = 0;
	while(!Q.empty())
	{
		int u = Q.top().second;Q.pop();	
		if(vis[u]) continue;
		vis[u] = true;
		for(int i = 0; i < G[u].size(); ++ i)
		{
			int v = G[u][i];
			if(dis[v] > dis[u] + W[u][i])
			{
				dis[v] = dis[u] + W[u][i];
				Q.push(make_pair(-dis[v], v));
			}
		}
	}
	return;
}

spfa:

void SPFA(int S)
{
	queue <int> Q;
	while(!Q.empty()) Q.pop();
	memset(inq, false, sizeof(inq));
	memset(dis, 0x7f, sizeof(dis));
        Q.push(S);
        inq[S] = true;
	dis[S] = 0;

	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		inq[u] = false;
		for(int i = 0; i < G[u].size(); ++ i)
		{
			int v = G[u][i], w = W[u][i];
			if(dis[v] > dis[u] + w)
			{
				dis[v] = dis[u] + w;
				if(!inq[v])
			        {
					inq[v] = 1;
					Q.push(v);
				}
			}
		}
	}
	return;
}
  • 若要求得从源点到终点所有路径,能够经过的边权最小的权值时,应将\(dis[v] = dis[u] + w\)改为\(dis[v] = min(w, dis[u])\),而求最大值的时候,在Dijkstra还需要把堆写成大根堆;
  • 当判断与源点相连是否存在负环的情况时,应当使用SPFA,在进行松弛操作的基础上加上一句话:\(cnt[v] = cnt[u] + 1\),其中\(cnt[i]\)指的是源点到节点i最短路径边的条数,则若\(cnt[v] ≥ n\),那么就判定为负环;
  • 通常情况下,如果求每个节点到源点的最短路时,须要考虑建反图,跑一遍最短路即可;若记录最短路的条数时,应当更新(或松弛)的时候累加;
  • 通常情况下,最短路更可能结合拓扑排序,请留意!

二、并查集

既能合并,又能查询的图论神器。
两种方法中,在图论中首选启发式合并。

//查询
int get(int x)
{
      if(fa[x] == x) return x;
      return get(fa[x]);
}

//合并
void merge(int x, int y)
{
      if(dep[x] < dep[y]) swap(x, y);
      int v = get(y);
      fa[v] = x;
      dep[x] += dep[y];
      return;
}

主要用于存在多个联通块的情况。
此结构非常精巧,一定格外留意。

三、拓扑排序

不得不说,如果学图论时没有熟练掌握该操作,将是非常的遗憾。
代码如下:

void topsort() {
	while(!Q.empty()) 
      {
            Q.pop();
      }
	
	for(int i = 1; i <= n; ++i) {
		if(deg[i] == 0) {
			Q.push(i);
		}
	}
	while(!Q.empty()){
		int x = Q.front();a.push_back(x);
		Q.pop();
		for(int i = 0; i < G[x].size(); ++ i){
			int y = G[x][i];
			--deg[y];
			if(deg[y] == 0){
				Q.push(y);
			}
		}
	}
	return;
}

拓扑排序用于判环、找结点的拓扑序等等。

图论常见解题方法和套路

标签:class   结构   启发式   code   top   second   line   spfa   get   

原文地址:https://www.cnblogs.com/zach20040914/p/13373077.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!