poj 1659(havel算法)

本文介绍了一种利用Havel算法解决图构造问题的方法,通过实例详细解释了算法的具体步骤,包括对序列排序、最大度数置零并与其他节点连接等关键操作。文章最后提供了代码实现和完整流程演示,帮助读者理解并应用该算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://poj.org/problem?id=1659

思路:  havel算法的应用:

(1)对序列从大到小进行排序。

(2)设最大的度数为 t ,把最大的度数置0,然后把最大度数后(不包括自己)的 t 个度数分别减1(意思就是把度数最大的点与后几个点进行连接)

(3)如果序列中出现了负数,证明无法构成。如果序列全部变为0,证明能构成,跳出循环。前两点不出现,就跳回第一步!

简单例子:

4 4 3 3 2 2

第二步后0 3 2 2 1 2

排完续后3 2 2 2 1 0

第二步后0 1 1 1 1 0

排完续后1 1 1 1 0 0

第二步后0 0 1 1 0 0

排完续后1 1 0 0 0 0

第二步后0 0 0 0 0 0

全为0,能构成图,跳出!

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define MAXN 14
 7 
 8 struct Node{
 9     int num,id;
10 }pp[MAXN];
11 
12 int n;
13 int map[MAXN][MAXN];
14 
15 int cmp(const Node &p,const Node &q)
16 {
17     return p.num>q.num;
18 }
19 
20 int main()
21 {
22     int _case;
23     scanf("%d",&_case);
24     while(_case--){
25         scanf("%d",&n);
26         for(int i=1;i<=n;i++){
27             scanf("%d",&pp[i].num);
28             pp[i].id=i;
29         }
30         memset(map,0,sizeof(map));
31         bool flag=true;
32         while(true){
33             sort(pp+1,pp+n+1,cmp);
34             if(pp[1].num==0)break;
35             for(int i=1;i<=pp[1].num;i++){
36                 pp[1+i].num--;
37                 if(pp[1+i].num<0)flag=false;
38                 map[pp[1].id][pp[1+i].id]=map[pp[1+i].id][pp[1].id]=1;
39             }
40             pp[1].num=0;
41             if(!flag)break;
42         }
43         if(flag){
44             puts("YES");
45             for(int i=1;i<=n;i++){
46                 printf("%d",map[i][1]);
47                 for(int j=2;j<=n;j++){
48                     printf(" %d",map[i][j]);
49                 }
50                 printf("\n");
51             }
52         }else
53             puts("NO");
54         if(_case)puts("");
55     }
56     return 0;
57 }
View Code

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值