POJ 2831 Prim

题意:给出一个n点m边的无向带权图,以及q个询问,每个询问查询当第i条边的权值改为x时,第i条边是否在该图的最小生成树(可能不唯一)之中。

思路:用Prim在n*n时间内求出最小生成树,并用Max[i][j]记录最小生成树上从i到j之间的边的权值最大值,每次询问只需判断两个节点之间边权最大值是否大于等于输入的x,若是则可以用这条修改过的边代替那条权值最大的边,输出Yes。注意可能有重边。

代码:

#include <cstdio>
#include <iostream>
#define For(i,j,k) for(int i = j;i <= (k);i ++)
using namespace std;

const int N = 1010, M = 100010, INF = 2e9;
int x[M], y[M], G[N][N], Max[N][N], dis[N], pre[N], vis[N], n, m, q;

void Prim(){
    For(i,2,n+1) dis[i] = INF;
    For(i,1,n){
        int k = n + 1;
        For(j,1,n)
            if(!vis[j] && dis[j] < dis[k])
                k = j;
        For(j,1,n)
            if(vis[j])
                Max[j][k] = Max[k][j] = max(Max[j][pre[k]], dis[k]);
        vis[k] = 1;
        For(j,1,n)
            if(!vis[j] && dis[j] > G[k][j])
                pre[j] = k, dis[j] = G[k][j];
    }
}

int main(){
    scanf("%d%d%d", &n, &m, &q);
    For(i,1,n)
        For(j,1,n) G[i][j] = INF;
    For(i,1,m){
        int w;
        scanf("%d%d%d", &x[i], &y[i], &w);
        G[x[i]][y[i]] = G[y[i]][x[i]] = min(G[x[i]][y[i]], w);
    }
    Prim();
    For(i,1,q){
        int k, t;
        scanf("%d%d", &k, &t);
        puts(Max[x[k]][y[k]] >= t ? "Yes" : "No");
    }
    return 0;
}
阅读更多
版权声明:本文为博主原创文章,转载需注明原文地址。 https://blog.csdn.net/dy0607/article/details/52372955
文章标签: prim poj
个人分类: 生成树
上一篇递推+矩阵快速幂
下一篇POJ 2449 A*k短路
想对作者说点什么? 我来说一句

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

关闭
关闭