“树”模板

一、最短路径

此处写两种方法: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;
        }
    }
}

 

猜你喜欢

转载自blog.csdn.net/weixin_44025325/article/details/87970526