Loading

[BalticOI 2002] Tennis Club (Day1) 解题报告

构造题

解题思路

贪心。优先满足想交朋友数最多的人。每次排序,让能交朋友多的人分别和第二,第三,……,交朋友。

代码实现

循环进行贪心分配。每次循环先排序,再分配朋友并更新需求。

代码

#include<bits/stdc++.h>
using namespace std;
int n;
bool f[1010][1010];
struct node{
	int v,id;
	friend bool operator <(node a,node b){
		return a.v>b.v;
	}
}a[1010];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i].v,a[i].id=i;
	for(int i=1;i<=n;i++){
		sort(a+1,a+n+1);
		for(int j=2;j<=a[1].v+1;j++){
			if(!a[j].v)return cout<<"NO SOLUTION"<<endl,0;
			a[j].v--;
			f[a[1].id][a[j].id]=1;
			f[a[j].id][a[1].id]=1;
		}
		a[1].v=0;
	}
	cout<<"SOLUTION\n";
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(f[i][j])cout<<j<<' ';
		}
		cout<<endl;
	}
	return 0;
} 

发散思考

线性的问题能不能转化到树上?
考虑下列问题:

  • 给定 \(n\) 个点的树,问能选出多少点对 \((u,v)\),满足 \(u,v\) 互相不为祖先,每个点只能被包含在一个点对中。
    这个问题将线性转化到了树上。
    由调整法,若所有子树的大小均不超过它们总大小的一半,根据经典的结论可知,匹配数能够达到上界。
    否则,记大小最大的子树是 \(v\),由调整法可知,存在一种最优方案使所有子树之间的匹配,存在于 \(v\) 和其它子树之间。那么我们只需优先在 \(v\) 的子树内部匹配,之后将剩余节点与其它子树匹配。
posted @ 2025-10-07 15:02  UserJCY  阅读(4)  评论(0)    收藏  举报
Title