zoukankan      html  css  js  c++  java
  • CF1041E Solution

    题目链接

    题解

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

    探讨限制条件:(1)(b)只能为(n),因为(n)一定是它所在连通分量中的最大值。(2)设(cnt_i)表示(i)作为(a)出现的次数,则(sumlimits_{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
    ");
    	for(int i=1;i<n;i++)
    	{
    		if(!vis[i]) continue;
    		if(cnt[i]>0) 
    		{
    			if(lst!=-1) printf("%d %d
    ",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
    ",lst,nxt);
    			vis[nxt]=1;
    			lst=nxt; cnt[i]--;
    		}
    	}
    	printf("%d %d
    ",lst,n);
    	return 0;
    } 
    

    参考博客

  • 相关阅读:
    解决Metasploit中shell乱码的问题
    AWVS扫描器的用法
    AWVS扫描器的用法
    AppScan扫描器的用法
    AppScan扫描器的用法
    Nessus扫描器的使用
    IPC$共享和其他共享(C$、D$)
    IPC$共享和其他共享(C$、D$)
    Windows中动态磁盘管理
    Windows中动态磁盘管理
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14257477.html
Copyright © 2011-2022 走看看