一 .图论:
最短路:
1. Dijkstra 算法:
/*用优先队列优化,vector存储边,
输入方式:
while (~scanf("%d%d", &m, &n) && m) {
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &a, &b, &c);
G[a].push_back(edge(b, c));
G[b].push_back(edge(a, c));
}
}
*/
#define INF 0x7fffffff
#define ll long long
#define MAX_V 1005
struct edge {
int to, cost;
edge() {}
edge(int a, int b) {
to = a;
cost = b;
}
};
typedef pair<int, int> P;
vector<edge> G[MAX_V];
int d[MAX_V];
int v, n, m;
void Dijkstra(int st) {
priority_queue<P, vector<P>, greater<P>> q;
for (int i = 0; i <= n; i++) {
d[i] = INF;
}
v = -1;
q.push(P(0, st));
d[st] = 0;
while (q.size()) {
P num = q.top(); q.pop();
v = num.second;
if (d[v] < num.first)
continue;
for (int i = 0; i < G[v].size(); i++) {
edge e = G[v][i];
if (d[e.to] > d[v] + e.cost) {
d[e.to] = d[v] + e.cost;
q.push(P(d[e.to], e.to));
}
}
}
}
强连通分量分解:
两个dfs 复杂度为(n + m)
//模板里的边保存一定要从0开始,不适用与从1开始
const int maxn = 1e5 + 10;
const int maxm = 5e5 + 10;
vector<int> G[maxn], rG[maxn], sc;
int n, m, topo[maxn], vis[maxn];
void addEdge(int from, int to) {
G[from].push_back(to);
rG[to].push_back(from);
}
void dfs(int v) {//第一遍dfs, 标记各个点的编号(后缀标记)
vis[v] = 1;
for (int i = 0; i < G[v].size(); i++) {
if (!vis[G[v][i]]) dfs(G[v][i]);
}
sc.push_back(v);
}
void rdfs(int v, int k) {//将有向图各个边反转,进行第二遍dfs, 找出连通分量, 顺便保存缩点后的有向无环图的拓扑序
vis[v] = 1;
topo[v] = k;
for (int i = 0; i < rG[v].size(); i++) {
if (!vis[rG[v][i]]) rdfs(rG[v][i], k);
}
}
int scc() {
sc.clear();
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++) {
if (!vis[i]) dfs(i);
}
memset(vis, 0, sizeof(vis));
int k = 0;
for (int i = sc.size() - 1; i >= 0; i--) {
if (!vis[sc[i]]) rdfs(sc[i], k++);
}
return k;
}