zoukankan      html  css  js  c++  java
  • cdoj913-握手 【Havel定理】

    http://acm.uestc.edu.cn/#/problem/show/913

    握手

    Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    一群人参加了一次聚会,其中有一些人是好朋友。一对朋友见面后握手且仅握一次手,并且每个人不会和自己握手(废话!)。现在告诉你每个人一共握了几次手,请你判断是否存在一种朋友关系满足每个人的握手数。

    Input

    输入多组数据,第一行一个数T,表述数据组数。每组数据第一行输入一个数n,表示有n个人参加了聚会,下一行有n个数,didn ,di表示第i个人的握手数。 (1n105 ,输入的所有d之和不超过5×105

    Output

    存在这种朋友关系输出YES,反之NO

    Sample input and output

    Sample InputSample Output
    3
    3
    0 1 1
    3
    2 2 2
    3
    1 1 1
    YES
    YES
    NO

    题解:用Havel定理解即可。

    握手定理:任意图所有顶点度数之和必为偶数。

    度序列:V(G)={v1,v2,....vn},称序列 {d(v1),d(v2),....d(vn)}为度序列。

    一个正整数序列(d1,d2,.....,dn)是度序列当且仅当

    Havel定理

    一个序列:

    是简单图的度序列当且仅当:

    算法流程:

    设序列有n个元素,d1,d2,....dn

    1、若序列中出现负数则无解,若序列全为为0则有解,否则转2。

    2、取出序列中最大值dmax,若dmax大于n-1,无解退出。否则取出剩下n-1个元素中前dmax大的dmax个元素,把这些元素依次减1后放回序列中,dmax舍弃,n=n-1。

    代码

     1 #include <fstream>
     2 #include <iostream>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <queue>
     6 
     7 using namespace std;
     8 
     9 const int N=100005;
    10 priority_queue<int> p;
    11 int n;
    12 int a[N],t[N];
    13 bool b;
    14 
    15 int main()
    16 {
    17     //freopen("D:\input.in","r",stdin);
    18     //freopen("D:\output.out","w",stdout);
    19     int T,cnt;
    20     scanf("%d",&T);
    21     while(T--){
    22         cnt=0;
    23         b=1;
    24         scanf("%d",&n);
    25         for(int i=0;i<n;i++){
    26             scanf("%d",&a[i]);
    27             cnt+=a[i];
    28         }
    29         if(cnt&1)   puts("NO");
    30         else{
    31             while(!p.empty())   p.pop();
    32             for(int i=0;i<n;i++)    p.push(a[i]);
    33             while(!p.empty()){
    34                 cnt=p.top();
    35                 p.pop();
    36                 if(cnt>=n){
    37                     b=0;
    38                     break;
    39                 }else if(cnt==0){
    40                     break;
    41                 }
    42                 if(p.size()<cnt){
    43                     b=0;
    44                     break;
    45                 }else{
    46                     for(int i=0;i<cnt;i++){
    47                         t[i]=p.top()-1;
    48                         p.pop();
    49                     }
    50                     if(t[cnt-1]<0){
    51                         b=0;
    52                         break;
    53                     }
    54                     for(int i=0;i<cnt;i++)
    55                         if(t[i])    p.push(t[i]);
    56                     n--;
    57                 }
    58             }
    59             if(b)   puts("YES");
    60             else    puts("NO");
    61         }
    62     }
    63     return 0;
    64 }
  • 相关阅读:
    并查集基础练习
    HDU1232——畅通工程
    二分答案——划分数列
    二分答案——收入计划
    动态规划练习题(2)
    动态规划程序设计2
    动态规划练习题(1)
    0/1背包
    P5024 保卫王国[倍增+dp]
    UVA11424 GCD
  • 原文地址:https://www.cnblogs.com/jiu0821/p/4618065.html
Copyright © 2011-2022 走看看