• 可图性判定HavelHakimi定理


    两个概念

    1、度序列

      若把图G所有顶点的度数排成一个序列S,则称S为图G的度序列。

    2、序列是可图的

      一个非负整数组成的序列如果是某个无向图的度序列,则称该序列是可图的。


    Havel-Hakimi定理

    由非负整数组成的非增序列S:d1, d2 ,..., dn (n≥2,d1≥1)是可图的,当且仅当序列S1:d2-1,d3-1,...,dd1+1-1,dd1+2,...,dn是可图的。其中,序列S1中有n-1个非负整数,S序列中d1后的前d1个度数(即d2~dd1+1)减1后构成S1中的前d1个数。


    应用:POJ 1659 Frogs' Neighborhood

    http://poj.org/problem?id=1659

    贴上一个博客

    http://blog.csdn.net/monkey_little/article/details/6358601

    对于该题目中的第一个序列,分析如下:

    具体操作时候,每次都把排序好的序列第一个元素处理完以后就置为0,加入到队列的最后。若是最后元素全为0,则该序列是可图的。若在中间出现某个元素减一之后变为负的,则说明此序列是不可图的。

    我的AC代码如下:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #define MAXN 10
     5 typedef struct Company
     6 {
     7   int data;
     8   int no;
     9 }Company;
    10 Company x[MAXN];
    11 int map[MAXN][MAXN];
    12 int Compare(const void *elem1, const void *elem2)
    13 {
    14   Company *p1 = (Company*)elem1;
    15   Company *p2 = (Company*)elem2;
    16 //  if (p1->data == p2->data)
    17 //  {
    18 //    return p1->no - p2->no;
    19 //  }
    20   return p2->data - p1->data;
    21 }
    22 int main()
    23 {
    24   int T, N;
    25   scanf("%d", &T);
    26   while(T--)
    27   {
    28     scanf("%d", &N);
    29     memset(map, 0, sizeof(map));
    30     int flag = 0;
    31     for (int i = 0; i < N; ++i)
    32     {
    33       scanf("%d", &x[i].data);
    34       x[i].no = i;
    35     }
    36     qsort(x, N, sizeof(Company), Compare);
    37     while(!flag && x[0].data)
    38     {
    39       int start = x[0].data;
    40       for (int i = 1; i < start+1; ++i)
    41       {
    42         x[i].data--;
    43         if (x[i].data < 0)
    44         {
    45           flag = 1;
    46           break;
    47         }
    48         map[x[0].no][x[i].no] = 1;
    49         map[x[i].no][x[0].no] = 1;
    50       }
    51       x[0].data = 0;
    52       qsort(x, N, sizeof(Company), Compare);
    53     }
    54     if (flag)
    55     {
    56       printf("NO\n");
    57     }else
    58     {
    59       printf("YES\n");
    60       for (int i = 0; i < N; ++i)
    61       {
    62         for (int j = 0; j < N; ++j)
    63         {
    64           printf(j == 0 ? "%d" : " %d", map[i][j]);
    65         }
    66         printf("\n");
    67       }
    68     }
    69     if (T)
    70     {
    71       printf("\n");
    72     }
    73   }
    74   return 0;
    75 }

    x.no这个属性用来记录每个输入数据的输入时的编号次序,以用来在map[][]数组填充1时用,否则不知道该x[?][?] = 1;

    flag是一个标志位,若中间有负数出现,就改变其值

    思路源自以下代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 struct node
     6 {
     7     int num,e;
     8 }x[15];
     9 bool map[15][15];
    10 int cmp(node a,node b)
    11 {
    12     if(a.num==b.num)
    13         return a.e<b.e;
    14     return a.num>b.num;
    15 }
    16 int judge(int n)
    17 {
    18     int i,num,tmp;
    19     while(1){
    20         sort(x+1,x+n+1,cmp);
    21         if(!x[1].num)
    22             return 1;//数组全为 0 的情况退出
    23         for(i=2;i<=x[1].num+1;i++){
    24             if(x[i].num>0){
    25                 x[i].num--;
    26                 map[x[1].e][x[i].e]=map[x[i].e][x[1].e]=1;
    27             }
    28             else
    29                 return 0;
    30         }
    31         x[1].num=0;
    32     }
    33 }
    34 int main()
    35 {
    36     int n,t,i,j;
    37     bool flag;
    38     scanf("%d",&t);
    39     while(t--){ 
    40         scanf("%d",&n);
    41         for(i=1;i<=n;i++){
    42             scanf("%d",&x[i].num);
    43             x[i].e=i;
    44         }
    45         memset(map,0,sizeof(map));
    46         flag=judge(n);
    47 
    48         if(flag){
    49             printf("YES/n");
    50             for(i=1;i<=n;i++){
    51                 for(j=1;j<=n;j++)
    52                     printf(j==1?"%d":" %d",map[i][j]);
    53                 printf("/n");
    54             }
    55         }
    56         else
    57             printf("NO/n");
    58         if(t)
    59             printf("/n");
    60     }
    61     return 0;
    62 }
    View Code
  • 相关阅读:
    Oracle11gR2 INDEX FAST FULL SCAN 成本计算
    SELECT MIN(ID),MAX(ID) FROM TABLE 优化问题
    一次帮助网友优化的SQL案例
    Oracle11gR2 全表扫描成本计算(非工作量模式noworkload)
    & 符号在 SQLPLUS 的转义
    通过设置SQLPLUS ARRAYSIZE(行预取)加快SQL返回速度
    [linux] 如何让你自己写的程序也支持自动补全(bash环境)
    linux 查看系统版本 命令
    ubuntu右键添加打开终端的快捷菜单
    ubuntu右键添加打开终端的快捷菜单
  • 原文地址:https://www.cnblogs.com/grubbyskyer/p/3849587.html
Copyright © 2020-2023  润新知