poj 1659 Frogs' Neighborhood(出入度、可图定理)

题意:我们常根据无向边来计算每个节点的度,现在反过来了,已知每个节点的度,问是否可图,若可图,输出一种情况。

分析:这是一道定理题,只要知道可图定理,就是so easy了

    可图定理:对每个节点的度从大到小排序,取第一个(最大)的度的节点,依次与其后(度)的节点连边,每连一条边,对应的度减1。然后重新排序,重复以上步骤,若度出现负值,则不可图。(若n个点中,某点的度>=n,那么也是不可能的)

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 const int MAXN=22;
 7 
 8 int a[MAXN],r[MAXN];
 9 int mp[MAXN][MAXN];
10 
11 void init(int n)
12 {
13     memset(a,0,sizeof(a));
14     memset(mp,0,sizeof(mp));
15     for(int i=0;i<n;i++)
16         r[i]=i;
17 }
18 
19 int cmp(int i,int j)
20 {
21     return a[i]>a[j];
22 }
23 
24 int check(int n)
25 {
26     for(int i=0;i<n;i++)
27     {
28         for(int j=1;j<1+a[r[0]];j++)
29         {
30             mp[r[0]][r[j]]=mp[r[j]][r[0]]=1;
31             a[r[j]]--;
32             if(a[r[j]]<0)
33                 return -1;
34         }
35         a[r[0]]=0;
36         sort(r,r+n,cmp);
37     }
38     return 1;
39 }
40 
41 void print(int n)
42 {
43     for(int i=0;i<n;i++)
44     {
45         for(int j=0;j<n;j++)
46             if(j==0)
47                 printf("%d",mp[i][j]);
48             else
49                 printf(" %d",mp[i][j]);
50         printf("\n");
51     }
52 }
53 
54 int main()
55 {
56     int T,n;
57     scanf("%d",&T);
58     while(T--)
59     {
60         scanf("%d",&n);
61         init(n);
62         for(int i=0;i<n;i++)
63             scanf("%d",&a[i]);
64         sort(r,r+n,cmp);
65 
66         if(check(n)==-1)
67             printf("NO\n");
68         else {
69             printf("YES\n");
70             print(n);
71         }
72         printf("\n");
73     }
74     return 0;
75 }
View Code

 

posted @ 2013-10-03 10:48  Thousand Sunny  阅读(295)  评论(0编辑  收藏  举报