2013长沙 G Graph Reconstruction (Havel-Hakimi定理)
Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge
Let there be a simple graph with N vertices but we just know the degree of each vertex. Is it possible to reconstruct the graph only by these information?
A simple graph is an undirected graph that has no loops (edges connected at both ends to the same vertex) and no more than one edge between any two different vertices. The degree of a vertex is the number of edges that connect to it.
Input
There are multiple cases. Each case contains two lines. The first line contains one integer N (2 ≤ N ≤ 100), the number of vertices in the graph. The second line conrains N integers in which the ith item is the degree of ith vertex and each degree is between 0 and N-1(inclusive).
Output
If the graph can be uniquely determined by the vertex degree information, output "UNIQUE" in the first line. Then output the graph.
If there are two or more different graphs can induce the same degree for all vertices, output "MULTIPLE" in the first line. Then output two different graphs in the following lines to proof.
If the vertex degree sequence cannot deduced any graph, just output "IMPOSSIBLE".
The output format of graph is as follows:
N E
u
1
u
2
... u
E
v
1
v
2
... v
EWhere N is the number of vertices and E is the number of edges, and {ui,vi} is the ith edge the the graph. The order of edges and the order of vertices in the edge representation is not important since we would use special judge to verify your answer. The number of each vertex is labeled from 1 to N. See sample output for more detail.
Sample Input
1
0
6
5 5 5 4 4 3
6
5 4 4 4 4 3
6
3 4 3 1 2 0
Sample Output
UNIQUE
1 0 UNIQUE
6 13
3 3 3 3 3 2 2 2 2 1 1 1 5
2 1 5 4 6 1 5 4 6 5 4 6 4
MULTIPLE
6 12
1 1 1 1 1 5 5 5 6 6 2 2
5 4 3 2 6 4 3 2 4 3 4 3
6 12
1 1 1 1 1 5 5 5 6 6 3 3
5 4 3 2 6 4 3 2 4 2 4 2
IMPOSSIBLE
havel定理的简介:
给定一个非负整数序列{d1,d2,...dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化。进一步,若图为简单图,则称此序列可简单图化。
可图化的判定比较简单:d1+d2+...dn=0(mod2)。关于具体图的构造,我们可以简单地把奇数度的点配对,剩下的全部搞成自环。
可简单图化的判定,有一个Havel定理,是说: 我们把序列排成不增序,即d1>=d2>=...>=dn,则d可简单图化当且仅当d'=(d2-1, d3-1, ... d(d1+1)-1, d(d1+2), d(d1+3), ... dn)可简单图化。这个定理写起来麻烦,实际上就是说,我们把d排序以后,找出度最大的点(设度为d1),把它和度次大的d1个点之间连边,然后这个点就可以不管了,一直继续这个过程,直到建出完整的图,或出现负度等明显不合理的情况。
定理的简单证明如下:
(<=)若d'可简单图化,我们只需把原图中的最大度点和d'中度最大的d1个点连边即可,易得此图必为简单图。
(=>)若d可简单图化,设得到的简单图为G。分两种情况考虑:
(a)若G中存在边(V1,V2), (V1,V3), ...(V1,V(d1+1)),则把这些边除去得简单图G',于是d'可简单图化为G'
(b)若存在点Vi,Vj使得i<j, (V1,Vi)不在G中,但(V1,Vj)在G中。这时,因为di>=dj,必存在k使得(Vi, Vk)在G中但(Vj,Vk)不在G中。这时我们可以令GG=G-{(Vi,Vk),(V1,Vj)}+{(Vk,Vj),(V1,Vi)}。GG的度序列仍为d,我们又回到了情况(a)。
判定过程:
(1)对当前数列排序,使其呈非递增序列
(2)从第二个数开始对其后d[1]个数字减1,d[1]代表排序后第1个数的值
(3)然后删除第一个之后对剩下的数继续排序
(3)一直循环直到当前序列出现负数(即不是可图的情况)或者当前序列全为0 (可图)时退出。
这题不知道为什么一直wa。。
附一个别人的AC代码,和自己的代码
code(self):
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<map>
#define INF 0x3f3f3f3f
#define M(a,b) memset(a,b,sizeof(a)) using namespace std; int N;
int line1[1006];
int line2[1006]; struct nod
{
int du;
int du1;
int num;
bool operator < (const nod & rhs) const
{
return du>rhs.du;
}
}point[1006]; bool cmp(nod a,nod b){return a.du1>b.du1;} int main()
{
int all = 0;
while(scanf("%d",&N)==1)
{
all = 0;
int ft = 0;
for(int i = 1;i<=N;i++)
{
scanf("%d",&point[i].du);
point[i].du1 = point[i].du;
point[i].num = i;
all+=point[i].du;
if(point[i].du<0) ft = 1;
}
if(ft == 1||all%2==1||point[1].du>N-1) {puts("IMPOSSIBLE");continue;}
int flag = 1;
int ct = 0;
for(int i = 1;i<=N;i++)
{
sort(point+1,point+N+1);
//for(int j = 1;j<=N;j++) cout<<point[j].du<<' ';
//cout<<endl;
if(point[1].du>N-i) {puts("IMPOSSIBLE");flag = 0;break;} if(point[1].du==0&&flag == 2)
{
puts("MULTIPLE");
printf("%d %d\n",N,all/2);
for(int j = 0;j<ct-1;j++)
printf("%d ",line1[j]);
printf("%d\n",line1[ct-1]);
for(int j = 0;j<ct-1;j++)
printf("%d ",line2[j]);
printf("%d\n",line2[ct-1]);
break;
} if(point[1].du==0)
{
puts("UNIQUE"); printf("%d %d\n",N,all/2);
if(all == 0) {puts("");puts("");break;}
for(int j = 0;j<ct-1;j++)
printf("%d ",line1[j]);
printf("%d\n",line1[ct-1]);
for(int j = 0;j<ct-1;j++)
printf("%d ",line2[j]);
printf("%d\n",line2[ct-1]);
break;
} if(point[point[1].du+2].du==point[1+point[1].du].du) {flag = 2;} for(int j = 2;j<=point[1].du+1;j++)
{
point[j].du--;
line1[ct] = point[1].num;
line2[ct] = point[j].num;
ct++;
if(point[j].du<0) {puts("IMPOSSIBLE");flag = 0; break;}
} point[1].du = 0;
if(flag == 0) break;
} if(flag==2)
{
ct = 0;
int fg = 0;
for(int i = 1;i<=N;i++)
{
sort(point+1,point+N+1,cmp);
//for(int j = 1;j<=N;j++) cout<<point[j].du1<<' ';
//cout<<endl;
if(point[1].du1==0)
{
printf("%d %d\n",N,all/2);
for(int j = 0;j<ct-1;j++)
printf("%d ",line1[j]);
printf("%d\n",line1[ct-1]);
for(int j = 0;j<ct-1;j++)
printf("%d ",line2[j]);
printf("%d\n",line2[ct-1]);
break;
} for(int j = 2;j<=point[1].du1+1;j++)
{
point[j].du1--;
line1[ct] = point[1].num;
line2[ct] = point[j].num;
ct++;
} if(point[point[1].du1+2].du1==point[1+point[1].du1].du1+1)
{
point[point[1].du1+2].du1--;
//line1[ct-1] = point[i].num;
line2[ct-1] = point[1+point[1].du1+1].num;
point[1+point[1].du1].du1++;
}
point[1].du1 = 0;
}
}
}
return 0;
}
code(others):
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=111;
int sum,n;
typedef pair<int ,int > P;
P deg[maxn];
P tmpdeg[maxn];
int ash1[maxn*maxn*2],ash2[maxn*maxn*2],alen; bool cmp(P A,P B)
{
if(A.first==B.first) return A.second<B.second;
return A.first>B.first;
}
void prints(){
printf("%d %d\n",n,sum>>1); if(alen>0)printf("%d",ash1[0]);
for(int i=1;i<alen;i++){
printf(" %d",ash1[i]);
}
puts("");
if(alen>0)printf("%d",ash2[0]);
for(int i=1;i<alen;i++){
printf(" %d",ash2[i]);
}
puts("");
} void cpy(){
for(int i=0;i<n;i++)tmpdeg[i]=deg[i];
sort(tmpdeg,tmpdeg+n,cmp);
} bool single;
bool rebuild(){
cpy();
alen=0;
single=true;
for(;tmpdeg[0].first>0;){
int amount=0;
for(int j=1;j<n;j++){
if(tmpdeg[j].first>0){
amount++;
}
}
if(amount<tmpdeg[0].first)return false;
if(single&&(tmpdeg[tmpdeg[0].first].first)==(tmpdeg[tmpdeg[0].first+1].first)){
single=false;
}
for(int j=1;j<=tmpdeg[0].first;j++){
tmpdeg[j].first--;
ash1[alen]=tmpdeg[0].second;
ash2[alen++]=tmpdeg[j].second;
} tmpdeg[0].first=0;
sort(tmpdeg,tmpdeg+n,cmp);
}
return true;
} bool rebuild2(){
cpy();
alen=0;
for(;tmpdeg[0].first>0;){
//if(amount<tmpdeg[0].first)return false;
if((tmpdeg[tmpdeg[0].first].first)==(tmpdeg[tmpdeg[0].first+1].first)){
swap(tmpdeg[tmpdeg[0].first].second,tmpdeg[tmpdeg[0].first+1].second);
}
for(int j=1;j<=tmpdeg[0].first;j++){
tmpdeg[j].first--;
ash1[alen]=tmpdeg[0].second;
ash2[alen++]=tmpdeg[j].second;
}
tmpdeg[0].first=0;
sort(tmpdeg,tmpdeg+n,cmp);
}
return true;
} int main(){
while(scanf("%d",&n)==1){
bool failed =false;
for(int i=1;i<=n;i++){
scanf("%d",&(deg[i-1].first));
deg[i-1].second=i;
if(deg[i-1].first<0)failed=true;
}
sort(deg,deg+n,cmp);
sum=0;
for(int i=0;i<n;i++){
if(deg[i].first>=n)failed=true;
sum+=deg[i].first;
}
if(sum&1)failed=true;
if(failed||!rebuild()){
puts("IMPOSSIBLE");
}
else if(single){
puts("UNIQUE");
prints();
}
else {
puts("MULTIPLE");
prints();
rebuild2();
prints();
}
}
return 0;
}
2013长沙 G Graph Reconstruction (Havel-Hakimi定理)的更多相关文章
- POJ1659 Frogs' Neighborhood(Havel–Hakimi定理)
题意 题目链接 \(T\)组数据,给出\(n\)个点的度数,问是否可以构造出一个简单图 Sol Havel–Hakimi定理: 给定一串有限多个非负整数组成的序列,是否存在一个简单图使得其度数列恰为这 ...
- 2013亚洲区域赛长沙站 ZOJ 3732 Graph Reconstruction
题目链接 Graph Reconstruction 题意 给你无向图每个点的度数, 问是否存在唯一解, 存在输出唯一解, 多解输出两个, 无解输出IMPOSSIBLE 思路 这里用到了 Havel-H ...
- Codeforces Round #192 (Div. 1) C. Graph Reconstruction 随机化
C. Graph Reconstruction Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/3 ...
- 2013长沙网络赛H题Hypersphere (蛋疼的题目 神似邀请赛A题)
Hypersphere Time Limit: 1 Second Memory Limit: 32768 KB In the world of k-dimension, there's a ...
- zoj3732&& hdu4797 Graph Reconstruction
Graph Reconstruction Time Limit: 2 Seconds Memory Limit: 65536 KB Special Judge Let there ...
- ZOJ3732 Graph Reconstruction Havel-Hakimi定理
分析: 给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化. 进一步,若图为简单图,则称此序列可简单图化 (来自百度百科) 可简单图化的判定可以用Have ...
- HDU 2454 Degree Sequence of Graph G——可简单图化&&Heavel定理
题意 给你一个度序列,问能否构成一个简单图. 分析 对于可图化,只要满足度数之和是偶数,即满足握手定理. 对于可简单图化,就是Heavel定理了. Heavel定理:把度序列排成不增序,即 $deg[ ...
- 【2013长沙区域赛】部分题解 hdu4791—4801
1001: 签到题,二分一下即可 代码: #include <set> #include <map> #include <cmath> #include <c ...
- The Ninth Hunan Collegiate Programming Contest (2013) Problem G
Problem G Good Teacher I want to be a good teacher, so at least I need to remember all the student n ...
随机推荐
- EF-CodeFirst-2玩的嗨
时间戳.复杂类型.GUID自增长 GUID自增长 GUID用于当主建那是好处多多,但是和int不同.EF不会自动识别第一个为类名+Id开头或int类型字段 去设置自增长.尴尬的GUID怎么玩呢.. D ...
- POJ 2823 Sliding Window + 单调队列
一.概念介绍 1. 双端队列 双端队列是一种线性表,是一种特殊的队列,遵守先进先出的原则.双端队列支持以下4种操作: (1) 从队首删除 (2) 从队尾删除 (3) 从队尾插入 (4) ...
- 【Beta】Daily Scrum 第二天
[目录] 1.任务安排 2.Burndown Chart 3.代码check-in 4.困难及总结 1.任务安排 学号尾数 昨天做的任务 今天做的任务 明天要做的任务 612 添加计时界面返回按键事件 ...
- 【Beta版本】冲刺-Day1
队伍:606notconnected 会议时间:12月9日 目录 一.行与思 二.站立式会议图片 三.燃尽图 四.代码Check-in 一.行与思 张斯巍(433) 今日进展:git学习,xml语言学 ...
- 数据结构与算法分析 - 网络流入门(Network Flow)
转载:网络流基础篇--Edmond-Karp算法 BY纳米黑客 网络流的相关定义: 源点:有n个点,有m条有向边,有一个点很特殊,只出不进,叫做源点. 汇点:另一个点也很特殊, ...
- iOS - libc++abi.dylib: terminate_handler unexpectedly threw an exception
代码出现crash,报错:libc++abi.dylib: terminate_handler unexpectedly threw an exception 当我们很明确是某一块代码执行导致了错误, ...
- ::before/:before和::after/:after的使用
::before/:before和::after/:after的使用 之前总是可以看到::before :before ::after :after,但是没有使用过,今天查了些资料,终于知道了他们的关 ...
- javascript中对象字面量的理解
javascript中对象字面量与数组字面量 第一部分 我们知道JavaScript中的数据类型有基本数据类型和引用类型,其中Object类型就是非常常用的类型.那么如果创建一个Object类型的实例 ...
- oneM2M
http://www.ccsa.org.cn/organization/intro.php?org=oneM2M 一.成立背景 随着物联网技术研发及市场推广的不断深入,全球各通信标准化组织都在加强物联 ...
- sql 中的运算符级别 如and or not
写了这么多简单的sql,很多东西忘记得差不多了,差点连最基本sql运算符优先级都忘了.平时最常用到and or的优先级都忘了 and的优先级高于or的优先级 举个例子 select * from us ...