题目链接:
http://acm.timus.ru/problem.aspx?space=1&num=1779
题目意思:
给n各点,让你构造一种连接方式,使得任意三个点的度数不一样。
解题思路:
利用贪心的思想这样构造:
从前至后构造节点度数分别为001122334455......
推出各节点的度数为:(节点标号从1开始)
sum[i]=i>>1(i为奇数)
sum[i]=i>>1-1(i为偶数)
然后从最后一个节点开始,因为它的度数最大,依次连线,当存在某个节点的度数已经达到sum[i]的时候,continue.
直到该点的度数达到。
当然当n为奇数时,存在一个问题,有的点的度数没达到,但又不能与前面的节点连,此时的处理是把该点与n节点相连。
代码;
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF (1<<30)
#define PI acos(-1.0)
using namespace std;
int sum[250];
int hav[250];
struct Edge
{
int a,b;
}edge[22000];
//从低往高一次凑出各点的度数,0011223344
void init() //预处理出各点的度数
{
for(int i=1;i<=200;i++)
{
if(i&1) //奇数的话,度数凑为i>>1
sum[i]=i>>1;
else //偶数的话
sum[i]=(i>>1)-1;
}
return ;
}
int main()
{
init();
int n;
while(scanf("%d",&n)!=EOF)
{
if(n==3) //特殊情况,特殊处理下
{
printf("1\n3 2\n");
continue;
}
int cnt=0;
memset(hav,0,sizeof(hav));//表示该节点已有的度数
for(int i=n;i>=1;i--)
{
if(hav[i]>=sum[i]) //该节点不用相连了
continue;
for(int j=i-1;j>=1;j--)
{
if(hav[j]>=sum[j])
continue;
edge[++cnt].a=i;
edge[cnt].b=j;
hav[i]++;
hav[j]++;
if(hav[i]>=sum[i])
break;
}
if(hav[i]<sum[i]) //如果不能够连,则它与n节点相连
{
edge[++cnt].a=n;
edge[cnt].b=i;
}
}
printf("%d\n",cnt);
//system("pause");
for(int i=1;i<=cnt;i++)
printf("%d %d\n",edge[i].a,edge[i].b);
}
return 0;
}