关闭

POJ 2831 Prim

标签: primpoj
117人阅读 评论(0) 收藏 举报
分类:

题意:给出一个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;
}
3
1

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6402次
    • 积分:509
    • 等级:
    • 排名:千里之外
    • 原创:38篇
    • 转载:0篇
    • 译文:0篇
    • 评论:28条
    友情链接