码迷,mamicode.com
首页 > 其他好文 > 详细

CF1041E Solution

时间:2021-01-12 11:02:30      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:复杂度   表示   lin   problem   出现   ORC   def   logs   return   

题目链接

题解

答案一定可以为一条链,因为对于答案树中的每个节点将其子节点从大到小排序放入链尾后依旧成立。

探讨限制条件:(1)\(b\)只能为\(n\),因为\(n\)一定是它所在连通分量中的最大值。(2)设\(cnt_i\)表示\(i\)作为\(a\)出现的次数,则\(\sum\limits_{j=1}^icnt_j<i\),因为每一个\(cnt\)都代表需要生成一个新的节点,而与\(i\)在同一个连通分量中的点一定\(\le i\),所以当\(\le i\)的点不够\(cnt\)时一定无法实现。

具体构造:从小到大枚举\(a_i\)加入链中,对于多组同样的\(a,b\),它们之间的点\(j\)一定\(\le a,b\),枚举\(j\)即可。时间复杂度为\(O(n^2)\)

AC题解

#include<bits/stdc++.h>
using namespace std;
const int N=1010,inf=0x3f3f3f3f;
int cnt[N];
bool vis[N];//i是否在已链中
int main()
{
	int n,a,b,sum=0;
	scanf("%d",&n);
    //限制条件(1)
	for(int i=1;i<n;i++)
	{
		scanf("%d%d",&a,&b);
		if(b!=n) {printf("NO"); return 0;}
		cnt[a]++; vis[a]=1;
	}
    //限制条件(2)
	for(int i=1;i<n;i++)
	{
		sum+=cnt[i];
		if(sum>i) {printf("NO"); return 0;}
	}
	int lst=-1,nxt;//lst:当前链尾,nxt:当前元素
	printf("YES\n");
	for(int i=1;i<n;i++)
	{
		if(!vis[i]) continue;
		if(cnt[i]>0) 
		{
			if(lst!=-1) printf("%d %d\n",lst,i);
			lst=i; cnt[i]--;
		}
		while(cnt[i]>0)//多组同样的a,b时
		{
			for(int j=1;j<i;j++)
				if(!vis[j]) {nxt=j; break;}
			printf("%d %d\n",lst,nxt);
			vis[nxt]=1;
			lst=nxt; cnt[i]--;
		}
	}
	printf("%d %d\n",lst,n);
	return 0;
} 

参考博客

CF1041E Solution

标签:复杂度   表示   lin   problem   出现   ORC   def   logs   return   

原文地址:https://www.cnblogs.com/violetholmes/p/14257477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!