1001. Battle Over Cities - Hard Version

这是一道关于战时城市联通的题目,要求在图中找到最需要保护的城市,以确保城市间能以最低成本保持联通。题目利用并查集解决,目标是找到在最小总花费中具有最大花费的城市进行保护。
摘要由CSDN通过智能技术生成

题意:

战争年代,公路对于两个城市的连接是至关重要的。现在有一个图,存在n个城市,m条路,每条路有个修建的费用weight,有一个标记位status表示这条是否被破坏,没有破坏的路,无需修建,无花费。现在这个图上的每个城市可能被破坏,破坏的城市,所有和他联通的路都不能通行,找一个方法把剩余城市连接起来,可能需要修路,修路有最小代价,而现在需要找出最需要保护的城市,保护其不被破坏。(最小代价中最大代价的城市需要保护)

方法:

使用并查集,最小中最大,

Sample Input 1:

4 5
1 2 1 1
1 3 1 1
2 3 1 0
2 4 1 1
3 4 1 0

Sample Output 1:

1 2
#include <iostream>
#include <bits/stdc++.h>

using namespace std;

struct road{
        int city1,city2,weight,status;
};

const int MAX = 10000000;
const int M = 500 * 499;
int cmp(const void *r1,const void *r2);
int findroot(int cityset[],int index);
int unionset(int cityset[],int index1,int index2);


int main(void)
{
    int n,m,i,j,usecnt = 0,destcnt = 0;
    road tmp;
    road *use, *destroyed;
    use = new road[M];
    destroyed = new road[M];
    scanf("%d %d",&n,&m);
    for(i = 0; i < m; i++)
    {
        scanf("%d %d %d %d", &tmp.city1, &tmp.city2, &tmp.weight, &tmp.status);
        if(tmp.status){
            use[usecnt++] = tmp;
        }
        else {
            destroyed[destcnt++] = tmp;
        }
    }
    qsort(destroyed, destcnt, sizeof(road), cmp);
    int *cityset = new int[n + 1];
    set<int> pro;
    int max_cost = 0, cnt, cost;
    for(i = 1; i< n + 1; i++)
    {
        for(j = 0;j<n+1;j++)
        {
            cityset[j]=-1;
        }
        cnt = cost = 0;
        for(j=0;j<usecnt&&cnt!=-n+1;j++)
        {
            if(use[j].city1==i||use[j].city2==i)
            {
                continue;
            }
            int index = unionset(cityset,use[j].city1,use[j].city2);
            if(index>0&&cityset[index]<cnt)
            {
                cnt = cityset[index];
            }
        }
        for(j=0;j<destcnt&&cnt!=-n+1;j++)
        {
            if(destroyed[j].city1==i||destroyed[j].city2==i)
            {
                continue;
            }
            int index = unionset(cityset,destroyed[j].city1,destroyed[j].city2);
            if(index>0){
                cnt = cityset[index] < cnt ? cityset[index]:cnt;
                cost += destroyed[j].weight;
            }
        }
        if(cnt== -n+1&& cost && cost == max_cost)
        {
            pro.insert(i);
        }
        else if(cnt == -n+1 && cost && cost > max_cost)
        {
            pro.clear();
            pro.insert(i);
            max_cost = cost;
        }
        else if(cnt > -n + 1 && max_cost == MAX)
        {
            pro.insert(i);
        }
        else if(cnt > -n + 1 && max_cost != MAX)
        {
            pro.clear();
            pro.insert(i);
            max_cost = MAX;
        }
    }
    if(pro.size()){
        set<int>::iterator it = pro.begin();
        printf("%d",*it++);
        for(; it != pro.end();it++)
        {
            printf(" %d",*it);
        }
    }
    else{
        puts("0");
    }
    delete[] cityset;
    delete[] use;
    delete[] destroyed;
    return 0;
}

int cmp(const void *v1, const void *v2)
{
    road *r1, *r2;
    r1 = (road *)v1;
    r2 = (road *)v2;
    return r1->weight - r2->weight;
}
int findroot(int cityset[], int index)
{
    if(cityset[index] < 0)
    {
        return index;
    }
    else
    {
        return cityset[index] = findroot(cityset, cityset[index]);
    }
}
int unionset(int cityset[], int index1, int index2)
{
    int root1,root2;
    root1 = findroot(cityset,index1);
    root2 = findroot(cityset,index2);
    if(root1 == root2)
    {
        return -1;
    }
    else
    {
        if(cityset[root1]>cityset[root2]){
            cityset[root2] += cityset[root1];
            cityset[root1] = root2;
            return root2;
        }
        else
        {
            cityset[root1] += cityset[root2];
            cityset[root2] = root1;
            return root1;
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值