• CF1391E Pairs of Pairs


    好神仙的一道题,考后想了很久也没想出来。

    考虑对原图随便跑一个 (dfs) 树出来。记 (dep_i) 为点 (i) 的深度,(K=lceilfrac{n}{2} ceil)

    1. 如果有 (forall dep_igeq K),那么我们就找到了一条长度大于等于 (K) 的路径,直接输出即可。
    2. 否则,我们把所有点按照 (dep_i) 的取值分类(相同的 (dep_i) 分为一类),在每一类里取出 (lfloor frac{cnt_i}{2} floor) 对点(任意配对,其中 (cnt_i) 表示深度为 (i) 的点的个数)。下面证明这样分组后,任意两组拼在一起的子图中边的条数 (leq 2):设你取出的两对点分别为 ({a,b}、{c,d}),其中 (dep_a=dep_ble dep_c=dep_d),显然根据无向图 (dfs) 树只有返祖边的性质,(a,b) 之间不可能有边且 (c,d) 之间不可能有边。(c) 最多与 (a,b) 其中的一个有边,(d) 同理也只与 (a,b) 中的一个有边。证毕。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    
    using namespace std;
    
    const int N=1000009;
    int head[N],cnt,n,m,dep[N],K,id[N],flag,F[N],vis[N],ans1[N],ans2[N];
    struct Edge
    {
    	int nxt,to;
    }g[N*2];
    
    void add(int from,int to)
    {
    	g[++cnt].nxt=head[from];
    	g[cnt].to=to;
    	head[from]=cnt;
    }
    
    void init()
    {
    	scanf("%d %d",&n,&m);K=n+1>>1;
    	cnt=0;
    	for (int i=1;i<=n;i++)
    		F[i]=dep[i]=head[i]=vis[i]=0;
    	for (int x,y,i=1;i<=m;i++)
    		scanf("%d %d",&x,&y),
    		add(x,y),add(y,x);	
    }
    
    void dfs(int x,int fa)
    {
    	if(flag) return;
    	vis[x]=1;
    	for (int i=head[x];i;i=g[i].nxt)
    	{
    		int v=g[i].to;
    		if(v==fa||vis[v]) continue;
    		dep[v]=dep[x]+1,F[v]=x;
    		if(!flag&&dep[v]>=K-1)
    		{
    			puts("PATH");
    			printf("%d
    ",K);
    			while(v)
    				printf("%d ",v),v=F[v];
    			puts("");
    			flag=1;
    		}
    		dfs(v,x);
    	}
    }
    
    bool cmp(int a,int b)
    {
    	return dep[a]<dep[b];
    }
    
    void work()
    {
    	int T;
    	scanf("%d",&T);
    	while(T--)
    	{
    		init();
    		flag=0;
    		dfs(1,-1);
    		if(!flag)
    		{
    			puts("PAIRING");
    			int tot=0;
    			for (int i=1;i<=n;i++)
    				id[i]=i;
    			sort(id+1,id+1+n,cmp);
    			for (int i=1;i<=n;i++)
    				if(dep[id[i]]==dep[id[i+1]])
    					ans1[++tot]=id[i],ans2[tot]=id[i+1],i++;
    			printf("%d
    ",tot);
    			for (int i=1;i<=tot;i++)
    				printf("%d %d
    ",ans1[i],ans2[i]);
    		}
    	}
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    android 模拟器手机如何添加文件到sd卡?
    Asp.Net 前台和后台交互的一些问题
    Cannot get WiFi AP state 错误
    MediaPlayer.getCurrentPosition IllegalStateException错误
    SQL Compare 错误 给定关键字不在字典中
    java.net.SocketException: Connection timed out的一种情况
    System services not available to Activities before onCreate()
    java.net.SocketException: Connection reset by peer
    卸载Microsoft Virtual WiFi Miniport Adapter 方法
    java 跳出 if
  • 原文地址:https://www.cnblogs.com/With-penguin/p/13472133.html
Copyright © 2020-2023  润新知