#306 (div.2) D. Regular Bridge

1.题目描述:点击打开链接

2.解题思路:本题属于一道图论的构造题。要求构造出一张无向图,其中所有的顶点的度数均为k,且至少含有一个桥。这道题在比赛时候没有任何思路,因为始终想象不出来k>1的情况。比赛结束后终于尝试画出了k=3的情况。然后摸索出来了做题方法。

首先,对于k等于偶数的情况,一定是不存在解的。假设顶点0是桥的一个端点,那么将桥断开后,它和所在的连通分量的2m-1个点相连(设k=2m),那么这2m-1个点需要再和2m-1个点相连接。假设这令外的2m-1个点都是新的点,那么这批点的度数将成为2m-1,之后需要两两相连,然而此时只有奇数个点,一定有一个点没办法配对,不满足度数等于k的条件。如果连接的点涉及第一批这2m-1个点,仍然会导出有一个点无法匹配的情况。

那么,当k为奇数的时候,只需要按照上述的方法进行构造,就一定可以保证得到合法的无向图。即:第一步,将0和2k-1设置为桥的两个端点。他们相连。第二步,0结点和1到k-1这k-1个点相连接。第三步,1结点到k-1个点分别伸出k-1条边和k到2k-2这k-1条边相连接。第四步,结点k到2k-2这k-1条边两两配对(注意此时k-1是偶数)。用同样的方法处理结点2k-1,即可构造出完整的图。

3.代码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<set>
#include<vector>
#include<stack>
#include<map>
#include<queue>
#include<deque>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<functional>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;


#define me(s) memset(s,0,sizeof(s))
#define For(i,n) for(int i=0;i<(n);i++)
#define pb push_back
#define sz size
#define clr clear
#define F(a,b) for(int i=a;b;i++)

const int N=500;
vector<int>g[N];
int k;

void addedge(int m)
{
    for(int i=1;i<=k-1;i++)//第二步
        g[m+0].pb(m+i);
    for(int i=1;i<=k-1;i++)
        for(int j=1;j<=k-1;j++)//第三步
            g[m+i].pb(m+k-1+j);
    for(int j=1;j<k-1;j+=2)//第四步
        g[m+k-1+j].pb(m+k+j);
}
int main()
{
   // freopen("t.txt","r",stdin);
    while(~scanf("%d",&k))
    {
        memset(g,0,sizeof(g));
        if(k&1)
        {
            puts("YES");
            int n=2*(2*k-1);
            int m=2*k*k-k;
            printf("%d %d\n",n,m);
            g[0].pb(2*k-1);//第一步
            addedge(0);
            addedge(2*k-1);
            for(int i=0;i<2*k-1;i++)
            {
                int len=g[i].size();
                for(int j=0;j<len;j++)
                    printf("%d %d\n",i+1,g[i][j]+1);
            }
            for(int i=0;i<2*k-1;i++)
            {
                int len=g[i+2*k-1].size();
                for(int j=0;j<len;j++)
                printf("%d %d\n",i+2*k,g[i+2*k-1][j]+1);
            }
        }
        else puts("NO");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值