一、最短路径
此处写两种方法:floyd算法和spfa算法
\\floyd,可以算出任意两条边的最短路径长度
void floyd()
{
for(k = 1;k <= n;k++)
for(i = 1;i <= n;i++)
for(j = 1;j <= n;j++)
if (i != j && i != k && j != k)
dp[i][j] = min(dp[i][j],dp[i][k] + dp[k][i]);
}
//spfa,可以算出指定源点到任意点的最短路径长。spfa不能处理负环。
struct node{
int v,w;
node(){}
node(int V,int W)
{
v = V;
w = W;
}
}
vector<node>G[MAXN + 5];
void spfa()
{
queue<int>q;
q.push(s); //s是源点,t是终点
flag[s] = 1;
cnt[1] = 1;
while(!q.empty())
{
int u = q.front();
q.pop();
flag[u] = 0;
for(int i = 0;i < G[u].size();i++){
int v = G[u][i].v,w = G[u][i].w;
if (dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
if (!flag[v]){
cnt[v]++;
if (cnt[v] >= n){
flag1 = 1; //此处可判断负环。flag1为true说明是负环。
return;
}
q.push(v);
flag[v] = 1;
}
}
}
}
}
二、最小生成树
此处写两种方法:prim算法和kruskal算法
//prim算法其实和dijkstra(算最短路径的一种算法)差不多,dijkstra不能处理负数边
void prim()
{
dis[s] = 0;
for(int i = 1;i <= n;i++){
int smin = 0x3f3f3f3f,k;
for(int j = 1;j <= n;j++)
if (dis[j] < smin && !flag[j]){
smin = dis[j];
k = j;
}
flag[k] = 1;
for(int j = 0;j < G[j].size();j++){
int v = G[k][j].v,w = G[k][j].w;
if (dis[v] > w && !flag[v])
dis[v] = w;
} //dijkstra算法只是判断语句不同,写法:if (dis[v] > dis[k] + w && !flag[j])
mst += dis[k]; //mst是答案
}
}
//kruskal算法
struct node{
int u,v,w;
}a[MAXN + 5];
bool cmp(node a,node b)
{
return a.w < b.w; //如是最大生成树,改为按w从大到小排序即可
}
void makeSet(int n)
{
for(int i = 1;i <= n;i++)
fa[i] = i;
}
void find(int x)
{
if (fa[x] != x)
fa[x] = find(fa[x]);
return fa[x];
}
void kruskal()
{
int cnt = 0,i;
for(int i = 1;i <= m;i++){ //m是总边数
int u = find(a[i].u),v = find(a[i].v);
if (u != v){
fa[v] = u;
cnt++;
ans += a[i].w;
if (cnt == n - 1)
break;
}
}
}