图论
拓扑排序
最小生成树
最短路
#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];
}