題目鏈接:
http://poj.org/problem?id=1659
解題思路:
題目有兩個要求,1是判斷給定這些點的度數,問這些點是否可圖;
2是需要輸出這些點與點之間的關係。
這個兩個問題是可以一起解決的。
首先我們可以將每個點的度數是可以計算出來的,按照度數將所有的點排序之後。
從度數最大的點開始,我們可以將其度數分配給比它度數小的一些點。
比如:
節點編號:2 3 4 1 5
節點度數:4 4 2 2 2
那麼我們可以將節點2的度數分配給節點:3 4 1 5,每個點分配一個度數。
那麼這幾個點的度數都需要減1,2號節點的度數變爲0,並且2號節點我們不需要再管它了。
就這樣一直更新下去,每次更新之後都需要對點進行排序,直到最後所有點的度數都爲0,那麼這些點是可圖的。
同時在做的過程當中,我們也能確定哪些邊是相連的。
源代碼:
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<string.h>
#include<string>
#include<map>
#include<vector>
#include<set>
#include<stack>
#include<queue>
#include<algorithm>
using namespace std;
const int N=15;
int edge[N][N],n;
struct node //記錄下每個點的度數
{
int id;
int du;
};
vector<node> v;
bool cmp(node a,node b) //按照度數對節點進行排序
{
return a.du>b.du;
}
int solve()
{
int i,j,len,k,t,x,y,du;
node temp;
memset(edge,0,sizeof(edge));
//取出度數最大的點,對其後面的點進行更新
while(1)
{
if(v.size()==0) return 1;
sort(v.begin(),v.end(),cmp);
x=v[0].id;
du=v[0].du;
if(du>=v.size()) return 0;
for(i=1;i<=du;i++)
{
y=v[i].id;
edge[x][y]=1;
edge[y][x]=1;
v[i].du--;
if(v[i].du<0)
return 0;
}
v.erase(v.begin());
}
return 1;
}
int main()
{
freopen("in.txt","r",stdin);
int cs,i,j,k,t;
node temp;
scanf("%d",&cs);
while(cs--){
scanf("%d",&n);
v.clear();
for(i=1;i<=n;i++){
temp.id=i;
scanf("%d",&temp.du);
v.push_back(temp);
}
if(solve()){
printf("YES\n");
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(j==1) printf("%d",edge[i][j]);
else printf(" %d",edge[i][j]);
}
printf("\n");
}
printf("\n");
}
else
printf("NO\n\n");
}
return 0;
}