---
# System prepended metadata

title: 圖論
tags: [Algorithm]

---

圖論
===
###### tags: `Algorithm`

## dijkstra
>[pf](https://blog.csdn.net/softee/article/details/39034129)
>[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/ShortestPath/Dijkstra.cpp#L15)

## bellmanford
>[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/ShortestPath/Bellman-Ford.cpp)
```cpp
// Bellman-Ford
// by. MiohitoKiri5474
#include<bits/stdc++.h>

using namespace std;

#define maxN 100005
#define pb push_back
typedef pair < int, int > pii;

vector < pii > edges[maxN];
int dis[maxN];

inline void BellmanFord ( int start ){
	memset ( dis, 0x3f3f3f, sizeof dis );
    dis[start]=0;
	queue < int > q;
	q.push ( start );
	while ( !q.empty() ){
		int now = q.front();
		q.pop();
		for ( auto i: edges[now] ){
			if ( dis[i.first] > dis[now] + i.second ){ // 檢查是否能更新
				q.push ( i.first );
				dis[i.first] = dis[now] + i.second;
			}
		}
	}
}
```

## SPFA
https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/ShortestPath/SPFA.cpp
```cpp
// SPFA
// basic on Bellman-Ford
// by. MiohitoKiri5474
#include<bits/stdc++.h>

using namespace std;

#define maxN 100005
#define pb push_back
typedef pair < int, int > pii;

vector < pii > edges[maxN];
int dis[maxN];
bool inQueue[maxN]; // 紀錄是否已經在queue中

inline void SPFA ( int start ){
	memset ( dis, 0x3f3f3f, sizeof dis );
    dis[start]=0;
	queue < int > q;
	q.push ( start );
	inQueue[start] = true;
	while ( !q.empty() ){
		int now = q.front();
		q.pop();
		inQueue[now] = false; // 紀錄已經取出
		random_shuffle ( edges.begin(), edges.end() );//打亂順序 有些測資會故意讓算法爆掉
		for ( auto i: edges[now] ){ // 跑過所有可以被now連結到的點
			if ( dis[i.first] > dis[now] + i.second ){
				dis[i.first] = dis[now] + i.second;
				if ( !inQueue[i.first] ){
					// 如果點沒有在queue中，再加入queue，並記錄已經在queue中
					inQueue[i.first] = true;
					q.push ( i.first );
				}
			}
		}
	}
}
```

## SLF
[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/ShortestPath/SPFA-buff-SLF.cpp)

## LLL
[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/ShortestPath/SPFA-buff-LLL.cpp)

## Floyd-warshall
[code]
(https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/ShortestPath/Floyd_Warshall.cpp)

## 最小生成樹
>[ref1](http://alrightchiu.github.io/SecondRound/minimum-spanning-treeintrojian-jie.html)
>[**ref2**](https://sites.google.com/site/zsgititit/home/jin-jiec-cheng-shi-she-ji-2/zui-xiao-sheng-cheng-shu)
>[演算法筆記](http://www.csie.ntnu.edu.tw/~u91029/SpanningTree.html)
:::info
* 生成樹:從一張圖取出一棵樹，包含圖上所有點。可能有許多種。
* 如果圖不連通,則可以求出最小生成森林
* 最小生成樹: 權重最小的生成樹
:::

### kruskal

```cpp
// Kruskal
// by. MiohitoKiri5474
#include<bits/stdc++.h>

using namespace std;

#define maxN 10005
#define pb push_back
typedef pair < int, int > pii;

int dis[maxN];

inline void init ( void ){
	for ( int i = 0 ; i < maxN ; i++ )
		dis[i] = i;
}

inline int find ( int a ){
	return dis[a] == a ? a : dis[a] = find ( dis[a] );
}

inline void Union ( int a, int b ){
	dis[find ( a )] = find ( b );
}

inline bool same ( int a, int b ){
	return find ( a ) == find ( b );
}

struct node{
	int u, v, w;
};

inline bool cmp ( node a, node b ){
	return a.w < b.w;
}

vector < node > edges;
vector < pii > mst[maxN];

inline void Kruskal ( void ){
	sort ( edges.begin(), edges.end(), cmp );
	for ( auto i: edges ){ // C++ 11寫法，不懂再來問
		if ( same ( i.u, i.v ) )
			continue;
		Union ( i.u, i.v );
		mst[i.u].pb ( pii ( i.v, i.w ) );
		mst[i.v].pb ( pii ( i.u, i.w ) );
	}
}
```
* dsu
### Prim
不斷找最小的邊
>[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/MST/Prim.cpp)


## LCA
:::info
最低共同祖先
:::
#### 倍增法
:::info
* 轉移方程
fa[i][j] = fa[fa[i][j-1]][j-1];
`i` :節點
`j` :i的第2^j倍祖先

![](https://i.imgur.com/QcEDgVE.png)
:::
>[ref](https://www.itread01.com/content/1542612733.html)

## Tarjan 尋找割點


* Tree edge：若vertex(Y)是被vertex(X)「發現」，則edge(X,Y)即為Tree edge，也就是Depth-First Tree中的edge。
    * 透過顏色判斷edge：當vertex(X)搜尋到vertex(Y)，且vertex(Y)為「白色」時，就會建立出Tree edge。
* Back edge：所有指向ancestor的edge，稱為Back edge。如圖六中，edge(F,B)與edge(H,G)。
    * 透過顏色判斷edge：當vertex(X)搜尋到vertex(Y)，且vertex(Y)為「灰色」，就會建立起Back edge，見圖三(j)、圖三(q)與圖六。
    
![](https://fsh0524.github.io/images/Articulation-Point/dfs3.png)

1. DFS的根節點有超過一條tree edge ,根節點必為AP
2. DFS 的任意非根節點 u 的子樹們沒有BackEdge通往 u 的祖先們時, u 必為AP
    * D[u]<=L[u],u!=root
D(u) DFS時深度
L(u) 子樹們的最低深度

* 尋找 L(u)
    * 

>[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/AP/Tarjan-AP.cpp)
>[ref](http://alrightchiu.github.io/SecondRound/graph-depth-first-searchdfsshen-du-you-xian-sou-xun.html)
>[ref](https://fsh0524.github.io/2016/03/03/Articulation-Point/)

## Tarjan's SCC
>[code](https://github.com/MiohitoKiri5474/Codes/blob/master/C%2B%2B/templates/SCC/Tarjan.cpp)

## 樹鏈
1.取得最大的子樹
