ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【2021集训队出题】交朋友

2022-01-25 20:35:50  阅读:178  来源: 互联网

标签:集训队 sz ++ auto px py 出题 2021 define


【2021集训队出题】交朋友

by AmanoKumiko

Description

给出一个图,构造尽量少的团,使得团中边覆盖了整个图

Input

第一行两个数\(n,m\),表示点数和边数

接下来\(m\)行,每行两个数\(x,y\),表示一条边

Output

第一行一个数\(k\),表示团的数量

接下来\(k\)行输出团

Sample Input

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

Sample Output

2
3 1 2 3
3 2 3 4

Data Constraint

\(n\le10^3\)

Solution

对于前两个点:手算

第三个点:由于给出的是二分图,所以团数就是边数

接下来开始动脑子了

1.我会暴力!(跑不动

2.我会随机!(分不多

3.一直贪心地找最大团!期望得分\(28\)

4.其它算法(估价函数、乱搞……)期望得分\(???\)

一种可行做法:

我们从始至终维护一个团的集合\(A\),保证它们中的边覆盖了整个图

那么依次执行以下操作:

(1)对于每个团,考虑每个点,若不在团内且可加入就放进去

(2)对于每个团,尝试删去,若仍覆盖了图,就删去

(3)对于每个团,考虑团中每个点,尝试删去,若仍覆盖了图,就删去

可以发现,\(|A|\)是不上升的

为了保证能弄出解,对枚举顺序随机打乱以下

对所有测试点运行一段时间(2h)即可

Code

#pragma GCC optimize("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define random(x) rand()%(x)
#define N 1010
#define M 1000010

int n,m,f[N][N],t[N][N],p[M],sz,x[M],y[M],vis[M],T,pnum[N];
vector<int>C[M],c[M];

int main(){
	freopen("friends10.in","r",stdin);
	scanf("%d%d",&n,&m);
	F(i,1,m){
		scanf("%d%d",&x[i],&y[i]);
		f[x[i]][y[i]]=f[y[i]][x[i]]=1;
		t[x[i]][y[i]]++;t[y[i]][x[i]]++;
		C[i].push_back(x[i]);
		C[i].push_back(y[i]);
	}
	sz=m;
	srand(time(0));
	F(i,1,n)p[i]=i;
	int lst=sz;
	while(sz>8486){
		srand(time(0));
		srand(rand());
		random_shuffle(p+1,p+n+1);
		F(j,1,sz) F(i,1,n){
			bool flag=1;
			for(auto px:C[j]){
				if(!f[px][p[i]]||px==p[i]){flag=0;break;}
			}
			if(flag){
				for(auto px:C[j]){
					t[px][p[i]]++;t[p[i]][px]++;
				}
				C[j].push_back(p[i]);
			}
		}
		random_shuffle(C+1,C+sz+1);
		F(i,1,sz)vis[i]=0;
		F(i,1,sz){
			bool flag=1;
			for(auto px:C[i]){
				for(auto py:C[i]){
					if(px==py)continue;
					t[px][py]--;
					if(t[px][py]<1)flag=0;
				}
			}
			if(flag)vis[i]=1;
			else{
				for(auto px:C[i]){
					for(auto py:C[i]){
						if(px==py)continue;
						t[px][py]++;
					}
				}
			}
		}
		F(j,1,sz)if(!vis[j]){
			random_shuffle(C[j].begin(),C[j].end());
			F(i,0,C[j].size()-1){
				bool flag=1;
				for(auto px:C[j]){
					if(px==C[j][i])continue;
					t[px][C[j][i]]--;t[C[j][i]][px]--;
					if(t[px][C[j][i]]<1||t[C[j][i]][px]<1)flag=0;
				}
				if(flag){
					swap(C[j][i],C[j][C[j].size()-1]);
					C[j].pop_back();
				}
				else{
					for(auto px:C[j]){
						if(px==C[j][i])continue;
						t[px][C[j][i]]++;t[C[j][i]][px]++;
					}
				}
				if(C[j].size()<1)vis[p[j]]=1;
			}
		}
		int tail=0;
		F(i,1,sz)if(!vis[i])c[++tail]=C[i];
		sz=tail;
		F(i,1,sz)swap(C[i],c[i]);
		if(sz<lst)printf("%d\n",sz);
		lst=sz;
	}
	freopen("friends10.out","w",stdout);
	printf("%d\n",sz);
	F(i,1,sz){
		printf("%d ",C[i].size());
		for(auto px:C[i])printf("%d ",px);
		printf("\n");
	}
	return 0;
}

标签:集训队,sz,++,auto,px,py,出题,2021,define
来源: https://www.cnblogs.com/AmanoKumiko/p/15844362.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有