并查集——Codeforces744A Hongcow Builds A Nation

来源:互联网 发布:真三国无双6 知乎 编辑:程序博客网 时间:2024/06/05 04:16

题面:cf744a
div.1A题。。。难度还算简单吧
首先我们把目前所有连通块全部求出来,这个用并查集维护一下
然后要求能连的边数最多,我们就把所有连通块连成最大团
不考虑原来边的数量m,每个连通块(最大团)的边数是(点数*(点数-1)/2)
然后考虑没有那个限制点(暂且这么说)的连通块,这些连通块两两可以连边
两两最多可以连的数量是(A的点数*B的点数)
最后考虑有限制点的连通块
因为这些连通块不能连边,所以我们找到这些中点数最多的连通块,然后和所有没有限制点的连通块连边(贪心)
计算方法同上,最后减掉那m条边就好了

#include <cstdio>#include <algorithm>#include <cmath>#include <cstring>#include <iostream>#include <ctime>#include <map>#include <queue>#include <cstdlib>#include <string>#include <climits>#include <set>#include <vector>using namespace std;bool vis[100001];int n,m,K,fa[100001],s[100001],p[100001]={0},c[100001];inline int getfather(int x){return fa[x]==x?x:fa[x]=getfather(fa[x]);}int main(){    scanf("%d%d%d",&n,&m,&K);    for(int i=0;i<=n;i++)fa[i]=i,s[i]=1;    for(int i=1;i<=K;i++)scanf("%d",&c[i]);    for(int i=1;i<=m;i++){        int x,y;scanf("%d%d",&x,&y);        int fx=getfather(x),fy=getfather(y);        if(fx!=fy)fa[fx]=fy,s[fy]+=s[fx];    }    for(int i=1;i<=K;i++)vis[getfather(c[i])]=1;    int ans=0,maxx=0;    for(int i=1;i<=n;i++){        int fx=getfather(i);        if(fx!=i)continue;        if(vis[fx])maxx=max(maxx,s[fx]);        else p[++p[0]]=s[fx];        ans+=s[fx]*(s[fx]-1)/2;    }    for(int i=1;i<=p[0];i++){        for(int j=i+1;j<=p[0];j++)ans+=p[i]*p[j];        ans+=p[i]*maxx;    }    printf("%d",ans-m);return 0;}
阅读全文
1 0
原创粉丝点击