1013 Battle Over Cities (25分)

题目的意思是先给定一些边,然后删除某个点,计算使剩下的点联通所需的边数。
用并查集做,跳过删除点对应的边初始化father数组,然后计算根结点个数,有几个根节点就有几个独立的集合。使这些集合联通的最小边数为集合数-1。最后-3是因为,跳出for时的i对应的father[i]!=-1,即此时的i已经不是根结点,-1;连接n个不相连的集合需要n-1条边,再-1;根结点中还有一个点是删除的点,所以总共需要-3。

#include <stdio.h>
#include <algorithm>

const int maxn=1010;
using namespace std;
int father[maxn]={0};
bool g[maxn][maxn]={false};

int cityNum,roadNum,queryNum;

int findFather(int index){
    int temp=index;
    while(father[index]!=-1){
        index=father[index];
    }
    while(father[temp]!=-1){
        int t=father[temp];
        father[temp]=index;
        temp=t;
    }
    return index;
}
int query(int id){
    fill(father+1,father+cityNum+1,-1);
    for(int i=1;i<=cityNum;i++){
        if(i==id)continue;
        for(int j=i;j<=cityNum;j++){
            if(j==id || !g[i][j])continue;
            father[i]=j;
        }
    }
    for(int i=1;i<=cityNum;i++){
        findFather(i);
    }
    sort(father+1,father+cityNum+1);
    int i;
    for(i=1;father[i]==-1;i++){}
    return i-3;
}

int main(){
    scanf("%d %d %d",&cityNum,&roadNum,&queryNum);
    for(int i=0;i<roadNum;i++){
        int a,b;
        scanf("%d %d",&a,&b);
        g[a][b]=g[b][a]=true;
    }
    for(int i=0;i<queryNum;i++){
        int queryid;
        scanf("%d",&queryid);
        printf("%d",query(queryid));
        if(i<queryNum-1)printf("\n");
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值