图论
拓扑排序
最小生成树
最短路
#include <bits/stdc++.h> #include <vector> #include <algorithm> using namespace std; const int MAXN = 1e5+10; int n, m; ////加带权边 //自建结构体 struct Edge { int v; int w; }; Edge make_Edge(int v, int w) { Edge cur; cur.v = v; cur.w = w; return cur; } vector<Edge> G[MAXN]; void addEdge(int u, int v,int w) { G[u].push_back(make_Edge(v, w)); G[v].push_back(make_Edge(u, w)); } //pair vector<pair<int, int>> A[MAXN]; void addedge(int u, int v, int w) { A[u].push_back(make_pair(v, w)); A[v].push_back(make_pair(u, w)); } int main() { system("pause"); return 0; } /*****************************************************/ /**********************拓扑排序************************/ /*****************************************************/ /*对DAG的顶点进行排序,要求:每个顶点出现且仅出现一次 对于(u, v),若排序后u在v前,则不存在v到u的路径。 即:能够到达某个顶点(能对其产生影响)u的所有点都在u前面*/ //拓扑进不去环 //用拓扑排序找环:基环内向树,迭代的删去所有的叶子 //,剩下的就是环 queue<int> q; vector<int> edge[MAXN]; vector<int> ans; //ans 为拓扑排序后的输出序列 int inDeg[MAXN]; // in degree int n, m; void topo() { for(int i=0; i < n; i++) //n 节点的总数 { if(inDeg[i] == 0) q.push(i); //将入度为0的点入队列 } while(!q.empty()) { int u, v; u = q.front(); q.pop(); // 选一个入度为0的点,出队列 ans.push_back(u); for(int i=0; i < edge[u].size(); i++) { v = edge[u][i]; inDeg[v]--; if(inDeg[v] == 0) q.push(v); } } //output if(ans.size()==n) { for(int i=0; i<ans.size(); i++) printf( "%d ",ans[i] ); printf("\n"); } else printf("No Answer!\n"); //无法拓扑排序 } /*****************************************************/ /*********************最小生成树***********************/ /*****************************************************/ /************************Prim*************************/ //每次把已访问的点的和未访问的点之间最短的边加入 //利用优先队列(堆)来存放边以获得最短的边 bool vis[MAXN]; int minc[MAXN]; priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q; //pair<长度, 编号> int prim() { int ans = 0; q.push(make_pair(0, 1)); while (!q.empty()) { int c = q.top().first, now = ed[q.top().second].to; if (!vis[now]) { vis[now] = true; ans += c; insert(ed[i].from, ed[i].to, ed[i].cost); insert(ed[i].to, ed[i].from, ed[i].cost); for (int i = he[now]; i; i = ne[i]) { Edge &e = ed[i]; if (minc[e.to] > e.cost && !vis[e.to]) { minc[e.to] = e.cost; q.push(make_pair(e.cost, i)); } } } } return ans; } /************************Kruskal*************************/ //按照边权进行排序,从小到大枚举每一条边,若不联通则加入最小生成 //树中。使用并查集维护连通性。 struct Edge { int u; int v; int w; }; int cmp1(Edge a, Edge b) { return a.w < b.w; } Edge edge[MAXN]; int n, m, tot; //tot is summary of the tree struct myDsu //并查集 disjoint set union { int f[MAXN]; void ini(int n) { for (int i = 1; i <= n; i++) { f[i] = i; } } void uni(int from, int to) { f[find(from)] = find(to); } int find(int x) { if(f[x] == x) { return x; } else { f[x] = find(f[x]) return f[x]; } } }dsu; void kruskal() { int k; dsu.ini(n); sort(edge, edge+m, cmp1); for(int i=0; i < m; i++) { if(k == n-1) break; //n个点需要n-1个边连接 if(dsu.find(edge[i].u) != dsu.find(edge[i].v)) { dsu.uni(edge[i].u,edge[i].v); tot += edge[i].w; k++; } } } /*****************************************************/ /***********************最短路*************************/ /*****************************************************/ /***********************Folyd*************************/ const int INF = 0x3f; int n, m; int d[INF][INF]; void floyd() { for(int k=1; k<=n; k++) { for(int i=1; i<=n; i++) { for(int j=1; i<=n; j++) { if(i != j && j != k && i != k) { d[i][j] = min(d[i][j], d[i][k] + d[k][j]); } } } } } /*********************dijkstra***********************/ int d[MAXN]; bool vis[MAXN]; priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > pq; int dijkstra(int s, int t) { memset(d, 0x3f, sizeof(d)); d[s] = 0; pq.push(make_pair(0, s)); while(!q.empty()) { int now = pq.top().second; q.pop(); if(!vis[now]) { vis[now] = true; for(int i = he[now]; i; i = ne[i]) { if(d[ed[i].to] > d[now] + ed[i].dist) { d[ed[i].to] = d[now] + ed[i].dist; pq.push(make_pair(d[ed[i].to], ed[i].to)); } } } } return d[t] == INF ? -1 : d[t]; } /***********************SPFA*************************/ //若某个点松弛了n次,说明有负环 //点已在队列不能入队,可以多次入队 struct Edge { int from, to, dist; }; Edge ed[MAXN]; int he[MAXN], ne[MAXN], etop = 1; //边编号从1开始,0代表没有下一条边,对应链表的NULL //he[i]代表点i边集中的第一条边编号,对应链表的head指针 //ne[i]代表边i的下一条边编号,对应链表中的next指针 //ed[i]代表边i的信息 const int INF = 0x3f3f3f3f; int d[MAXN]; bool vis[MAXN]; queue<int> q; inline int spfa(int s, int t) { q.push(s); vis[s] = true; memset(d, 0x3f, sizeof(d)); d[s] = 0; while (!q.empty()) { int now = q.front(); q.pop(); vis[now] = false; for (int i = he[now]; i; i = ne[i]) { if (d[now] + ed[i].dist < d[ed[i].to]) { d[ed[i].to] = d[now] + ed[i].dist; if (!vis[ed[i].to]) { q.push(ed[i].to); vis[ed[i].to] = true; } } } } return d[t] == INF ? -1 : d[t]; }
来源:https://www.cnblogs.com/lil-laian/p/12343488.html