Codeforces 550D Regular Bridge (构造)

题意:一个图,图的每个顶点度数都为k,问这个图中是否可能含有割边。有救输出图,无NO。


思路:

假设存在度数为k 的这样一个图,利用对称的思想,去掉割边后得到两个完全相同的子图。子图顶点数为n,则子图的总度数为n*k-1,因总度数必为偶数,故n,k都为奇数。

然后构图就要看你脑洞有多大了。

我是这样做的,度为k-1的点s与k-1个点相连。再令设两点i、j,都与那k-1个点相连,

这样i、j的度为k-1了,再让i、j相连,除那k-1个点,其他的点都满足要求了。

而这k-1个点每个点的度数都差k-3度。怎么办?

把这k-1个点想成一个正k-1边形,除了对角线上的点不相连,其余的都连上,这样就完全满足要求了。


代码写的并不是很好。。。

#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdlib>

#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 1005;

int k;
vector<int> G[maxn];
bool mark[maxn];

void add_Edge(int from,int to){
    G[from].push_back(to);
    G[to].push_back(from);
}

int main(){
    memset(mark,0,sizeof(mark));
    scanf("%d",&k);
    if(k % 2 == 0) printf("NO\n");
    else{
        if(k == 1){
            printf("YES\n2 1\n1 2\n");
        }else{
            printf("YES\n");
            printf("%d %d\n",2*k+4,k*(k+2));
            add_Edge(0,k+2);
            add_Edge(k,k+1);
            add_Edge(2*k+2,2*k+3);
            for(int i=1;i<=k-1;i++){
                add_Edge(0,i);add_Edge(k,i); add_Edge(k+1,i);
            }
            for(int i=k+3;i<=2*k+1;i++) {
                add_Edge(k+2,i); add_Edge(2*k+2,i); add_Edge(2*k+3,i);
            }
            if(k > 3){
                for(int i=1;i<=k-1;i++){
                    for(int j=1;j<=k-1;j++){
                        if(i == j || 2*abs(i - j) == k-1) continue;
                        add_Edge(i,j);
                    }
                }
                for(int i=k+3;i<=2*k+1;i++){
                    for(int j=k+3;j<=2*k+1;j++){
                        if(i == j || 2*abs(i - j) == k-1) continue;
                        add_Edge(i,j);
                    }
                }
            }
            for(int i=0;i<=2*k+3;i++){
                sort(G[i].begin(),G[i].end());
                G[i].erase(unique(G[i].begin(),G[i].end()),G[i].end());
                mark[i] = true;
                for(int j=0;j<G[i].size();j++){
                    int v = G[i][j];
                    if(!mark[v]) printf("%d %d\n",i+1,v+1);
                }
            }
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值