您的位置:首页 > 其它

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

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

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

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

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int MAXN=22;

int a[MAXN],r[MAXN];
int mp[MAXN][MAXN];

void init(int n)
{
memset(a,0,sizeof(a));
memset(mp,0,sizeof(mp));
for(int i=0;i<n;i++)
r[i]=i;
}

int cmp(int i,int j)
{
return a[i]>a[j];
}

int check(int n)
{
for(int i=0;i<n;i++)
{
for(int j=1;j<1+a[r[0]];j++)
{
mp[r[0]][r[j]]=mp[r[j]][r[0]]=1;
a[r[j]]--;
if(a[r[j]]<0)
return -1;
}
a[r[0]]=0;
sort(r,r+n,cmp);
}
return 1;
}

void print(int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
if(j==0)
printf("%d",mp[i][j]);
else
printf(" %d",mp[i][j]);
printf("\n");
}
}

int main()
{
int T,n;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
init(n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(r,r+n,cmp);

if(check(n)==-1)
printf("NO\n");
else {
printf("YES\n");
print(n);
}
printf("\n");
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: