PAT顶级(MST)——1001 Battle Over Cities - Hard Version (35 分)

1001 Battle Over Cities - Hard Version (35 分)


解题思路:

枚举每个城市,破坏连着它的边,残留网络中跑克鲁斯卡尔最小生成树(并查集+边排序,排序在枚举城市循环外,一次排序即可),对于status=1的边是已经建成的,修改其cost=0即可。

坑点:

若破坏某个城市后网络不连通,则该城市的代价为最大(如果有多个这样的城市,则输出多个)

代码:

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define  rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 998244353;
const int MAX1 = 100005;
const int MAX2 = 300005;
inline ll read() {
    ll x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch>'9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * f;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
#define int ll
struct ss
{
    int s, e, status, cost;
}x[1000000];
bool cmp(ss a, ss b)
{
    return a.status>b.status||(a.status==b.status&&a.cost < b.cost);
}
int fa[505];
ll value[505];
int find(int r)
{
    return fa[r] == r ? r : fa[r] = find(fa[r]);
}
void join(int x, int y, int city, ss c)
{
    int fx = find(x), fy = find(y);
    if (fx != fy&&!c.status)value[city] += c.cost;
    fa[fx] = fy;
}

signed main()
{
    int n = rd, m = rd;
    for (int i = 0; i < m; i++)
    {
        x[i].s = rd;
        x[i].e = rd;
        x[i].cost = rd;
        x[i].status = rd;
    }
    sort(x, x + m, cmp);
    for (int i = 1; i <= n; i++)
    {
        for (int i = 1; i <= n; i++)fa[i] = i;
        for (int j = 0; j < m; j++)
        {
            if (x[j].s == i || x[j].e == i)continue;
            join(x[j].s, x[j].e, i, x[j]);
        }
        int p = (i == 1 ? 2 : 1);
        for (int k = 1; k <= n; k++)
        {
            if (find(p) != find(k) && k != i)
            {
                value[i] = 1e18;
            }
        }
    }
    ll ma = 0;
    for (int i = 1; i <= n; i++)
    {
        ma = max(value[i], ma);
    }
    int k = 0;
    if (ma == 0)
    {
        cout << 0;
        return 0;
    }
    for (int i = 1; i <= n; i++)
    {
        if (ma == value[i]) {
            if (k >= 1)cout << ' ';
            cout << i;
            k++;
        }

    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值