【模板】最短路&&最小生成树

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Loi_Shirley/article/details/52962735

3.给一张图,有三种操作:
1.询问两点间的最短路
2.询问整张图的最小生成树
3.加边
都是双向边,数据范围1 <= n <= 10000,1 <= m <= 100000 1 <= q <= 100;

论最短路的正(防)确(爆)写法
论最小生成树的正确玩法
论加边的正确处理

最短路给出Dijkstra和spfa
最小生成树使用kruskal

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 2000005;
const int INF = 2147483641;
int first[MAXN],next[MAXN],dis[MAXN];
int n,m,qq,se,ee,p,tot = 0;
int fa[MAXN],deep[MAXN];
bool use[MAXN];

inline int read()
{
    char ch = getchar();
    int f = 1, x = 0;
    while(!(ch >= '0' && ch <= '9')){if(ch == '-')f=-1;ch = getchar();}
    while(ch >= '0' && ch <= '9') {x = x* 10 + (ch- '0');ch = getchar();}
    return x * f;
} 

void init()
{
    memset(deep,0,sizeof(deep));
    for(int i = 1; i <= n; i ++)
        fa[i] = i;
    return;
}

struct edge
{
    int f,t,v;
}l[MAXN],e[MAXN];

void build(int f,int t,int v)
{
    l[++ tot] = (edge){f,t,v};
    next[tot] = first[f];
    first[f] = tot;
    return;
}

bool cmp(edge a,edge b)
{
    return a.v < b.v;
}

deque < int >q;
void spfa(int s)
{
    memset(dis,0x3f,sizeof(dis));
    memset(use,0,sizeof(use));
    dis[s] = 0;
    use[s] = true;
    while(!q.empty())   q.pop_front();
    q.push_back(s);
    q.push_back(0);

    while(!q.empty())
    {
        int u = q.front();
        use[u] = false;
        q.pop_front();
        for(int i = first[u]; i != -1; i = next[i])
        {
            int w = l[i].t;
            if(dis[w] > dis[u] + l[i].v)
            {
                dis[w] = dis[u] + l[i].v;
                if(use[w] == false)
                {
                    use[w] = true;
                    if(q.empty())   q.push_back(w);
                    if(dis[w] < dis[q.front()])
                        q.push_front(w);
                    else
                        q.push_back(w);
                }
            }
        }
    }
    return;
}
/*struct re
{
    int u,v;
    bool operator < (const re &b)const
    {
        return v > b.v;
    }
};

priority_queue < re > q;
int dij(int s,int e)
{
    memset(use,0,sizeof(use));
    while(!q.empty())   q.pop();
    q.push((re){s,0});
    while(!q.empty())
    {
        re us = q.top();
        q.pop();
        int u = us.u;
        if(u == e)  return us.v;
        if(use[u])  continue;
        use[u] = true;
        for(int i = first[u]; i != -1; i = next[i])
        {
            int w = l[i].t;
            int rs = us.v + l[i].v;
            q.push((re){w,rs});
        }
    }
    return -1;
}*/

int find(int x)
{
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void merge(int x,int y)
{
    x = find(x),y = find(y);
    if(deep[x] > deep[y])
        swap(x,y);
    fa[x] = y;
    if(deep[x] == deep[y])
        deep[y] ++;
    return;
}

bool same(int x,int y)
{
    return find(x) == find(y);
}

int kru()
{
    sort(e + 1,e + 1 + m,cmp);
    init();
    int ans = 0;
    for(int i = 1; i <= m; i ++)
        if(!same(e[i].f,e[i].t))
            ans += e[i].v,merge(e[i].f,e[i].t);
    return ans;
}

int main()
{
    memset(first,0xff,sizeof(first));
    n = read(),m = read();
    for(int i = 1; i <= m; i ++)
    {
        e[i].f = read(),e[i].t = read(),e[i].v = read();
        build(e[i].f,e[i].t,e[i].v);
        build(e[i].t,e[i].f,e[i].v);
    }
    qq = read();
    for(int i = 1; i <= qq; i ++)
    {
        p = read();
        if(p == 1)
        {
            se = read(),ee = read();
            spfa(se);
            printf("%d\n",dis[ee]);
        //  printf("%d\n",dij(se,ee));
        }
        else if(p == 2)
            printf("%d\n",kru());
        else if(p == 3)
        {
            m ++;
            e[m].f = read(),e[m].t = read(),e[m].v = read();
            build(e[m].f,e[m].t,e[m].v);
            build(e[m].t,e[m].f,e[m].v);
        }
    }
    return 0;
}
阅读更多
换一批

没有更多推荐了,返回首页