CodeForces - 744A Hongcow Builds A Nation 【并查集】

传送门

Description
|Hongcow is ruler of the world. As ruler of the world, he wants to make it easier for people to travel by road within their own countries.

The world can be modeled as an undirected graph with n nodes and m edges. k of the nodes are home to the governments of the k countries that make up the world.

There is at most one edge connecting any two nodes and no edge connects a node to itself. Furthermore, for any two nodes corresponding to governments, there is no path between those two nodes. Any graph that satisfies all of these conditions is stable.

Hongcow wants to add as many edges as possible to the graph while keeping it stable. Determine the maximum number of edges Hongcow can add.

Input
The first line of input will contain three integers n, m and k (1 ≤ n ≤ 1 000, 0 ≤ m ≤ 100 000, 1 ≤ k ≤ n) — the number of vertices and edges in the graph, and the number of vertices that are homes of the government.

The next line of input will contain k integers c1, c2, ..., ck (1 ≤ ci ≤ n). These integers will be pairwise distinct and denote the nodes that are home to the governments in this world.

The following m lines of input will contain two integers ui and vi (1 ≤ ui, vi ≤ n). This denotes an undirected edge between nodes ui and vi.

It is guaranteed that the graph described by the input is stable.

Output
Output a single integer, the maximum number of edges Hongcow can add to the graph while keeping it stable


题意:给你N个点,M条无向边,其中里面有K个国家政府,在不让任意两个国家政府连接的前提下,最多还能连接几条边。(输入肯定保证没有两个政府相连,没有自环,没有重边)

思路:我们把点集分为重要点集(政府),和非重要点集(非政府)。这道题要求尽量加更多的边,我们需要贪心策略,将非重要点集所有补成一个完全图,重要点集各自补成完全图,再从重要点集里面选择一个包含点最多的一起集合,然后和非重要完全图在补成一个完全图。


附上代码:

///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const int INF=0x3f3f3f3f;

int n,m,k;

bool city[1005];
int edge[1005];
int point[1005];

int p[1005];
int find(int x)
{
    return p[x]==x?x:p[x]=find(p[x]);
}

void init()
{
    memset(city,0,sizeof(city));
    memset(edge,0,sizeof(edge));
    memset(point,0,sizeof(point));
    for(int i=1;i<=1000;i++)
    {
        p[i]=i;
        point[i]=1;
    }
}

int main()
{
    init();
    int s,e,x,y;
    scanf("%d %d %d",&n,&m,&k);
    for(int i=1;i<=k;i++)
    {
        scanf("%d",&x);
        city[x]=1;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&s,&e);
        x=find(s);
        y=find(e);
        if(x!=y)
        {
            p[x]=y;
            edge[y]+=edge[x]+1;
            point[y]+=point[x];
        }
        else
            edge[x]++;
    }
    int root[1005],sum=0;
    map<int,int>q;
    for(int i=1;i<=n;i++)
    {
        root[i]=find(i);
        if(city[i])
            q[root[i]]=2;///标记为含有政府
        else
            q[root[i]]=max(q[root[i]],1);
    }
    map<int,int>::iterator u=q.begin();
    int no_p=0,no_e=0;
    int maxn=0;
    while(u!=q.end())
    {
        s=u->first;
        if(u->second==1)///不包含政府的
        {
            no_p+=point[s];
            no_e+=edge[s];
        }
        else            ///包含政府的
        {
            sum+=(point[s]*(point[s]-1))/2-edge[s];
            ///补成完全图
            maxn=max(maxn,point[s]);
        }
        u++;
    }
    sum+=no_p*(no_p-1)/2-no_e;///非政府补成完全图
    sum+=no_p*maxn;///含点最多的政府和非政府补成完全图
    printf("%d\n",sum);
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值