Graph Reconstruction

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定理)的更多相关文章

  1. POJ1659 Frogs' Neighborhood(Havel–Hakimi定理)

    题意 题目链接 \(T\)组数据,给出\(n\)个点的度数,问是否可以构造出一个简单图 Sol Havel–Hakimi定理: 给定一串有限多个非负整数组成的序列,是否存在一个简单图使得其度数列恰为这 ...

  2. 2013亚洲区域赛长沙站 ZOJ 3732 Graph Reconstruction

    题目链接 Graph Reconstruction 题意 给你无向图每个点的度数, 问是否存在唯一解, 存在输出唯一解, 多解输出两个, 无解输出IMPOSSIBLE 思路 这里用到了 Havel-H ...

  3. Codeforces Round #192 (Div. 1) C. Graph Reconstruction 随机化

    C. Graph Reconstruction Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/3 ...

  4. 2013长沙网络赛H题Hypersphere (蛋疼的题目 神似邀请赛A题)

    Hypersphere Time Limit: 1 Second       Memory Limit: 32768 KB In the world of k-dimension, there's a ...

  5. zoj3732&& hdu4797 Graph Reconstruction

    Graph Reconstruction Time Limit: 2 Seconds      Memory Limit: 65536 KB      Special Judge Let there ...

  6. ZOJ3732 Graph Reconstruction Havel-Hakimi定理

    分析: 给定一个非负整数序列{dn},若存在一个无向图使得图中各点的度与此序列一一对应,则称此序列可图化. 进一步,若图为简单图,则称此序列可简单图化 (来自百度百科) 可简单图化的判定可以用Have ...

  7. HDU 2454 Degree Sequence of Graph G——可简单图化&&Heavel定理

    题意 给你一个度序列,问能否构成一个简单图. 分析 对于可图化,只要满足度数之和是偶数,即满足握手定理. 对于可简单图化,就是Heavel定理了. Heavel定理:把度序列排成不增序,即 $deg[ ...

  8. 【2013长沙区域赛】部分题解 hdu4791—4801

    1001: 签到题,二分一下即可 代码: #include <set> #include <map> #include <cmath> #include <c ...

  9. 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 ...

随机推荐

  1. rsync服务器安装配置

    #rsync指定端口号(10002)1 rsync -e 'ssh -p 10002' rsync (server -- client) #2014-3-3 -----------server---- ...

  2. Exception:A generic error occurred in GDI+

    分析: 一般出现这种问题都是GDI和原数据(比如Bitmap)是同一个实体,只不过是两个引用.换句话说就是这个路径的图片被GDI占用啦. 还有一种情况是路径有问题. 场景一: WPF的Image控件的 ...

  3. python标准模块(一)

    本文会涉及到的模块: time datetime sys os random re hashlib 模块,用若干代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能 ...

  4. Yocto开发笔记之《Tip-bitbake常用命令》(QQ交流群:519230208)

    开了一个交流群,欢迎爱好者和开发者一起交流,转载请注明出处. QQ群:519230208,为避免广告骚扰,申请时请注明 “开发者” 字样 =============================== ...

  5. 在Android上实现使用Facebook登录(基于Facebook SDK 3.5)

    准备工作: 1.       Facebook帐号,国内开发者需要一个vpn帐号(网页可以浏览,手机可以访问) 2.       使用Facebook的SDK做应用需要一个Key Hashes值. 2 ...

  6. js获取当前域名及获取页面完整地址并做判断

    <script language="javascript"> //获取域名 hostName = window.location.host; host2=documen ...

  7. 磁盘里的B,MB,GB,TB储存单位是怎么换算大小的?

    磁盘里的B,MB,GB,TB是怎么换算大小的? 1TB=1024GB1GB=1024MB1MB=1024KB1KB=1024Byte 注:Byte就是B也就是字节KB是千字节MB是兆GB是吉字节 即千 ...

  8. 完整的ajax请求投票点赞功能的实现【数据库表一(票数)表二(ip限制重复投票)】

    前端php页面 <?php if(isset($_GET['id'])){ $id=$_GET['id']; } include('data/conn.php'); $sqls="se ...

  9. EasyUI学习笔记之panel

    <easyUI panel 属性:> <!--引入easyUI panel 组件 设置宽,高,定义标题(默认在左上角),设置图标iconCls:'icon-ok',引入工具tools ...

  10. 结合Hadoop,简单理解SSH

    在启动dfs和yarn时,需要多次输入密码,不但启动本机进程还有辅服务器启动那些节点也需要相应密码,主与辅服务器之间是通过SSH连接的,并发送操作指令 一.ssh密码远程登录 1.使用ssh连接另一台 ...