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;
}