Codeforces 550D Regular Bridge【思维+构造】好题!

D. Regular Bridge
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

An undirected graph is called k-regular, if the degrees of all its vertices are equal k. An edge of a connected graph is called a bridge, if after removing it the graph is being split into two connected components.

Build a connected undirected k-regular graph containing at least one bridge, or else state that such graph doesn't exist.

Input

The single line of the input contains integer k (1 ≤ k ≤ 100) — the required degree of the vertices of the regular graph.

Output

Print "NO" (without quotes), if such graph doesn't exist.

Otherwise, print "YES" in the first line and the description of any suitable graph in the next lines.

The description of the made graph must start with numbers n and m — the number of vertices and edges respectively.

Each of the next m lines must contain two integers, a and b (1 ≤ a, b ≤ n, a ≠ b), that mean that there is an edge connecting the vertices a and b. A graph shouldn't contain multiple edges and edges that lead from a vertex to itself. A graph must be connected, the degrees of all vertices of the graph must be equal k. At least one edge of the graph must be a bridge. You can print the edges of the graph in any order. You can print the ends of each edge in any order.

The constructed graph must contain at most 106 vertices and 106 edges (it is guaranteed that if at least one graph that meets the requirements exists, then there also exists the graph with at most 106 vertices and at most 106 edges).

Examples
Input
1
Output
YES
2 1
1 2
Note

In the sample from the statement there is a suitable graph consisting of two vertices, connected by a single edge.


题目大意:

是否存在一个无向图,使得每个点的度数都是K,并且包含一个边是割边(去掉这个边之后,原来是整个连通图,变成两部分连通图)。


思路:


1、考虑割边,肯定对于这条割边的两个端点u,v来讲,其两侧一定是对称结构。

那么我们只要考虑出来任意一边的图形,那么另外一边就肯定是一模一样的无误了。


2、根据简单分析,K=2的时候是无解的,K=3的时候在纸上画一画是有解的,K=4的时候又是无解的,那么我们可以大胆假设,K为偶数的时候,都是无解。

那么考虑有解的时候,K是奇数,那么我们考虑v的右侧部分的构图(并且假设此时K==5):

①首先肯定,v的右侧一定要连出去四个点(标号2345),这样能够使得degree【v】==5.

②接下来考虑,如果不引入新的点,即使右边的四个点构成了一个完全图,也并不能使得每个点的度数都达到5.那么显然我们要引入一个新的点(标号6).

③再考虑,如果此时将右部分的图(不包括1)变成一个完全图,那么2345标号的点能够保证度为5.但是6的度数并不能达到5,因为其他点都和1进行了连接。那么肯定要再引入一个新的点(标号7).很显然,七号点可以和剩余的五个点(2 3 4 5 6)分别连一条边,使得七号节点的度变成5.那么在7号点连边之前,那么如果我们将23456的度都变成4(距离目标度数差1)即可。

④那么我们贪心的连边,将所有编号的点,按照65432的顺序去连边,使得6号点都能和这4个点连起来。

那么就有:

⑤最后再将7号点和23456连一条边即可。

⑥然后对称过去到左侧一个包含7个点的一个图,再将1连接左侧8号点一下即可。


3、同理,我们只要先将1号点连出去度-1条边,然后引入一个新的点,连边使得234.......K+1个点的度都变成K-1.然后再引入一个新的点使得这个点连入2345......K+1.使得一侧的图的点的度都满足要求即可。

然后再对称过去一下,就可以了。


Ac代码:

#include<stdio.h>
#include<string.h>
using namespace std;
int degree[20000];
int ans[200000][2];
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        if(n==1)
        {
            printf("YES\n");
            printf("2 1\n1 2\n");
            continue;
        }
        if(n%2==0)
        {
            printf("NO\n");
            continue;
        }
        int cnt=0;
        printf("YES\n");
        memset(degree,0,sizeof(degree));
        for(int i=1;i<=10000;i++)degree[i]=n;
        for(int i=2;i<=n;i++)
        {
            ans[cnt][0]=1;
            ans[cnt++][1]=i;
            degree[i]--;
        }
        for(int i=2;i<=n+1;i++)
        {
            for(int j=n+1;j>=i+1;j--)
            {
                if(degree[i]>1&°ree[j]>1)
                {
                    ans[cnt][0]=i;
                    ans[cnt++][1]=j;
                    degree[i]--;
                    degree[j]--;
                }
            }
        }
        for(int i=2;i<=n+1;i++)
        {
            ans[cnt][0]=n+2;
            ans[cnt++][1]=i;
        }
        ans[cnt][0]=(10+(n-3)/2*4)/2+1;
        ans[cnt++][1]=1;
        int tmp=cnt;
        for(int i=0;i<tmp-1;i++)
        {
            ans[cnt][0]=ans[i][0]+(10+(n-3)/2*4)/2;
            ans[cnt++][1]=ans[i][1]+(10+(n-3)/2*4)/2;
        }
        printf("%d %d\n",10+(n-3)/2*4,cnt);
        for(int i=0;i<cnt;i++)
        {
            printf("%d %d\n",ans[i][0],ans[i][1]);
        }
    }
}










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值