1 条题解

  • 0
    @ 2026-5-5 18:19:42

    决定小团体强度的值有两个:

    • 团体内的最小度。
    • 团体人数。

    我们可以考虑枚举最小度求最大的团体人数。

    我们发现小于原图最小度的度肯定不优,因为原图最小度可以直接选择包含全图使团体人数最大,这给了我们一个启发。

    在之后,由于我们要增大团体内的最小度,所以最小度的点不会被包含,因此可以考虑删掉这些点。

    这个时候问题由变回了原样,我们可以继续找最小度的点,如此类推。

    注意到动态删点加维护连通块大小不好做,但是动态维护点的度数不难,我们先利用 set 维护删点顺序,再倒着加点,变成动态加点维护连通块大小,并查集即可维护。

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    const LL N=3e5+5;
    LL n,m,x,y,ans,fa[N],a[N],du[N],d[N],sz[N],vis[N];
    vector<LL>v[N];
    stack<LL>s;
    set<pair<LL,LL>>p;
    LL find(LL x)
    {
    	if(fa[x]==x)return x;
    	return fa[x]=find(fa[x]);
    }
    int main()
    {
    	scanf("%lld%lld",&n,&m);
    	for(int i=1;i<=n;i++)fa[i]=i,a[i]=i,sz[i]=1;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%lld%lld",&x,&y);
    		v[x].push_back(y);
    		v[y].push_back(x);
    		du[x]++,du[y]++;	
    	}
    	for(int i=1;i<=n;i++)
    	{
    		p.insert({du[i],i});
    	}
    	while(!p.empty())
    	{
    		LL t=(*p.begin()).second;
    		p.erase(p.begin());
    		s.push(t);
    		d[t]=du[t];
    		for(LL i:v[t])
    		{
    			if(d[i])continue;
    			p.erase(p.lower_bound({du[i],i}));
    			du[i]--;
    			p.insert({du[i],i});
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		LL t=s.top();
    		vis[t]=1;
    		s.pop();
    		for(LL j:v[t])
    		{
    			if(vis[j]==0)continue;
    			LL fx=find(t),fy=find(j);
    			if(fx!=fy)
    			{
    				fa[fx]=fy;
    				sz[fy]+=sz[fx];
    			}
    		}
    		ans=max(ans,sz[find(t)]*d[t]);
    	}
    	printf("%lld",ans);
    	return 0;
    }
    
    • 1

    [USACO22DEC] Strongest Friendship Group G

    信息

    ID
    7608
    时间
    2000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    15
    已通过
    6
    上传者