• 【构造】Tinkoff Challenge


    考试的时候想的是,将所有的完全子图缩起来,然后如果剩下的是一条链,依次对其进行标号即可。

    看了官方题解,发现完全子图这个条件太强了,缩点的条件仅仅需要保证原本两个点的“邻接表”相同即可。(注意这里的“邻接表”需要把其自身也放进去)

    自己构造一下,发现这个比较容易理解。

    被缩在一起的点的标号相同。如果缩完是一条链,对其依次进行标号。否则无解。

    复杂度发现比较鬼畜,但是想一下就会知道其不会太高。官方说可以证明是

    #include<cstdio>
    #include<vector>
    #include<set>
    #include<algorithm>
    using namespace std;
    int n,m,xs[300010],ys[300010];
    struct data{
    	int id;
    	vector<int>ljb;
    }nodes[300010];
    bool cmp(const data &a,const data &b){
    	return a.ljb<b.ljb;
    }
    int bel[300010],nn,col[300010],du[300010];
    set<pair<int,int> >S;
    vector<int>G[300010];
    int pen;
    void dfs(int U){
    	col[U]=++pen;
    	for(int i=0;i<G[U].size();++i){
    		if(!col[G[U][i]]){
    			dfs(G[U][i]);
    		}
    	}
    }
    int main(){
    //	freopen("d.in","r",stdin);
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;++i){
    		scanf("%d%d",&xs[i],&ys[i]);
    		nodes[xs[i]].ljb.push_back(ys[i]);
    		nodes[ys[i]].ljb.push_back(xs[i]);
    	}
    	for(int i=1;i<=n;++i){
    		nodes[i].id=i;
    		nodes[i].ljb.push_back(i);
    		sort(nodes[i].ljb.begin(),nodes[i].ljb.end());
    	}
    	sort(nodes+1,nodes+n+1,cmp);
    	int sta;
    	for(int i=1;i<=n;++i){
    		if(nodes[i].ljb!=nodes[i-1].ljb){
    			sta=i;
    		}
    		if(nodes[i].ljb!=nodes[i+1].ljb){
    			++nn;
    			for(int j=sta;j<=i;++j){
    				bel[nodes[j].id]=nn;
    			}
    		}
    	}
    	for(int i=1;i<=m;++i){
    		if(bel[xs[i]]!=bel[ys[i]]){
    			if(S.find(make_pair(bel[xs[i]],bel[ys[i]]))==S.end() &&
    			S.find(make_pair(bel[ys[i]],bel[xs[i]]))==S.end()){
    				S.insert(make_pair(bel[xs[i]],bel[ys[i]]));
    				S.insert(make_pair(bel[ys[i]],bel[xs[i]]));
    				G[bel[xs[i]]].push_back(bel[ys[i]]);
    				G[bel[ys[i]]].push_back(bel[xs[i]]);
    				++du[bel[xs[i]]];
    				++du[bel[ys[i]]];
    			}
    		}
    	}
    	int cnt=0;
    	for(int i=1;i<=nn;++i){
    		if(du[i]==1){
    			++cnt;
    		}
    		else if(du[i]>2){
    			puts("NO");
    			return 0;
    		}
    	}
    	if(cnt==2 || (nn==1 && cnt==0)){
    		for(int i=1;i<=nn;++i){
    			if(du[i]==1 || du[i]==0){
    				dfs(i);
    				break;
    			}
    		}
    		puts("YES");
    		for(int i=1;i<n;++i){
    			printf("%d ",col[bel[i]]);
    		}
    		printf("%d
    ",col[bel[n]]);
    	}
    	else{
    		puts("NO");
    	}
    	return 0;
    }
  • 相关阅读:
    c语言 12
    c语言中用结构体表示点的坐标,并计算两点之间的距离
    c语言 12
    c语言中结构体数组
    c语言 12-3
    c语言 12-2
    codevs3164 质因数分解
    codevs4438 YJQ Runs Upstairs
    codevs4439 YJQ Requires Food
    codevs4437 YJQ Arranges Sequences
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6870336.html
Copyright © 2020-2023  润新知