Frogs' Neighborhood POJ - 1659 havel定理

19 篇文章 0 订阅
19 篇文章 0 订阅

havel定理:判断度数序列是否可图(简单图)

题意
未名湖附近共有N个大小湖泊L1, L2, …, Ln(其中包括未名湖),每个湖泊Li里住着一只青蛙Fi(1 ≤i ≤ N)。如果湖泊Li和Lj之间有水路相连(无向图),则青蛙Fi和Fj互称为邻居。现在已知每只青蛙的邻居数目x1,x2, …, xn,请你给出每两个湖泊之间的相连关系。
思路
直接贪心是有误的:1 2 3 2 0
用 havel定理
判定过程:
(1)对当前数列排序,使其呈递减,
(2)从S【2】开始对其后S【1】个数字-1,
(3) 一直循环直到当前序列出现负数(即不是可图的情况)或者当前序列全为0 (可图)时退出。
代码

/*
 * Author       :  Echo
 * Email        :  1666424499@qq.com  
 * Description  :   
 * Created Time :  2017/10/15 16:40:58
 * Last Modify  :  2017/10/15 17:33:16
 * File Name    :  write.cpp
 */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
using namespace std;
const int maxn=20;
const int maxm=1e4+100;
const int INF=1e9;
int n;
struct node{
    int cnt,id;
}an[maxn];
int mp[maxn][maxn];
bool cmp(node a,node b){
    return a.cnt>b.cnt;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf("%d",&an[i].cnt);
            an[i].id=i;
        }
        memset(mp,0,sizeof(mp));
        int flg=1;
        while(1){
            sort(an+1,an+n+1,cmp);
            if(an[1].cnt==0)break;
            for(int i=2;i<=n;i++){
                if(an[1].cnt==0)break;
                an[1].cnt--;
                an[i].cnt--;
                mp[an[1].id][an[i].id]=mp[an[i].id][an[1].id]=1;
                if(an[i].cnt<0){
                    flg=0;
                    break;
                }
            }
            if(flg==0)break;
        }
        if(flg==0){
            printf("NO\n\n");
            continue;
        }
        printf("YES\n");
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                printf("%d%c",mp[i][j],j==n? '\n':' ');
            }
        }
        printf("\n");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值