POJ 1659 Frogs' Neighborhood【Havel算法】
题意: 告诉你有 N 湖是,并告诉你和每个湖相连湖的个数,问你能否找到一种可能的连通方式。
分析: 问题的目的就是看看能否重建这个连通图,可以用Havel算法
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,能构成图,跳出!
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> #include<stdlib.h> #include<string.h> struct node { int xu,num; }q[12]; int g[12][12]; int cmp(const void*p1,const void*p2) { struct node* c=(node*)p1; struct node* d=(node*)p2; return d->num-c->num; } int main() { int t,i,j,n,flag; scanf("%d",&t); while(t--) { scanf("%d",&n); flag=0; for(i=1;i<=n;i++) { scanf("%d",&q[i].num); q[i].xu=i; } memset(g,0,sizeof(g)); while(1) { qsort(q+1,n,sizeof(q[0]),cmp); if(q[1].num==0)break; for(i=1;i<=q[1].num;i++) { q[1+i].num-=1; g[q[1].xu][q[1+i].xu]=g[q[1+i].xu][q[1].xu]=1; if(q[1+i].num<0) { flag=1; goto loop; } } q[1].num=0; } loop: if(flag) printf("NO\n"); else { printf("YES\n"); for(i=1;i<=n;i++) for(j=1;j<=n;j++) printf("%d%c",g[i][j],j==n?'\n':' '); } printf("\n"); } return 0; }