Problem: Frogs’ Neighborhood
Description: 给你一个无向图顶点度的序列,让你求出这个图的邻接矩阵。
Solution: 我的做法是
DFS
,虽然这个题可以用Havel算法快速搞定,但是我之前不知道这个算法,而且一开始我的
DFS
也爆栈了。原因是我每层搜的是邻接矩阵的一个位置的两种状态:
0,1
。这样的话,最多要搜55层。必然会爆。后来看到了网上的解题报告。我觉得很妙。他采用了状态压缩的方式。搜的是每一行的状态。那么这样的话就只要搜10层就好了,而矩阵中的每一行状态都可以用一个二进制数来表示。这样就过了。
Code(C++):
#include <stdio.h>
#include <string.h>
const int M=11;
int n;
int map[M][M];
int row[M];
int States[M][1<<M];
int top[M];
bool f;
int judge(int x)
{
int sum=0;
while(x){
sum+=(x&1);
x>>=1;
}
return sum;
}
void get_States()
{
memset(top,0,sizeof(top));
for(int i=0;i<(1<<n);i++){
int tmp=judge(i);
States[tmp][top[tmp]++]=i;
}
}
void dfs(int x)
{
if(x==n+1){
f=true;
return ;
}
if(f)
return ;
for(int i=0;i<top[row[x]];i++){
int s=States[row[x]][i];
if(s&(1<<(n-x)))
continue;
int tmp[M]={0};
bool h=true;
for(int j=n;j>=1&&s;j--,s>>=1)
tmp[j]=(s&1);
for(int j=1;j<x;j++)
if(tmp[j]!=map[x][j]){
h=false;
break;
}
if(!h)
continue;
for(int j=x+1;j<=n;j++)
map[x][j]=map[j][x]=tmp[j];
dfs(x+1);
if(f)
return ;
for(int j=x+1;j<=n;j++)
map[j][x]=0;
}
}
int main()
{
int N;
for(scanf("%d",&N);N--;){
memset(row,0,sizeof(row));
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&row[i]);
f=false;
get_States();
memset(map,0,sizeof(map));
dfs(1);
if(!f)
puts("NO");
else{
puts("YES");
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
printf("%d%c",map[i][j],
j==n? '\n':' ');
}
puts("");
}
return 0;
}