博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2013长沙 G Graph Reconstruction (Havel-Hakimi定理)
阅读量:5923 次
发布时间:2019-06-19

本文共 4646 字,大约阅读时间需要 15 分钟。

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 i
th item is the degree of i
th 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 Eu
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 {u
i,v
i} is the i
th 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

1065 5 5 4 4 365 4 4 4 4 363 4 3 1 2 0

Sample Output

UNIQUE1 0UNIQUE6 133 3 3 3 3 2 2 2 2 1 1 1 52 1 5 4 6 1 5 4 6 5 4 6 4MULTIPLE6 121 1 1 1 1 5 5 5 6 6 2 25 4 3 2 6 4 3 2 4 3 4 36 121 1 1 1 1 5 5 5 6 6 3 35 4 3 2 6 4 3 2 4 2 4 2IMPOSSIBLE

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
#include
#include
#include
#include
#include
#include
#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<
<<' '; //cout<
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

 code(others):

#include 
#include
#include
using namespace std;const int maxn=111;int sum,n;typedef pair
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.first;}void prints(){ printf("%d %d\n",n,sum>>1); if(alen>0)printf("%d",ash1[0]); for(int i=1;i
0)printf("%d",ash2[0]); for(int i=1;i
0;){ int amount=0; for(int j=1;j
0){ amount++; } } if(amount
0;){ //if(amount
=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;}

  

转载于:https://www.cnblogs.com/haohaooo/p/4008218.html

你可能感兴趣的文章
2017 年移动应用开发十大趋势
查看>>
用美化包设置Java Swing LookAndFeel
查看>>
各硬盘编号含义
查看>>
Git分布式版本工具的部署与使用
查看>>
第1章 Java 多线程技能
查看>>
test_app.sh
查看>>
php持续集成——在Centos+Jenkins+Ant+PHPUnit跑通了单元测试
查看>>
打包安装android应用报错:如下
查看>>
网站排名下降的原因,网站排名下降怎么办?
查看>>
PDF文件怎么修改,怎样替换PDF中的一页
查看>>
Infortrend亮相2019年台北国际电脑展,横向扩展NAS集群、云存储、AI一体机集体登场...
查看>>
三次握手、四次挥手
查看>>
Shell(6)- awk 命令用法
查看>>
多个生成树协议--mstp
查看>>
Arcpy的使用总结a
查看>>
人工智能AI,到底可以做什么?Face To
查看>>
CentOS系统时间与UTC时间不一致的解决方法
查看>>
干货|可视化分析 web 访问日志
查看>>
Introduction to Elasticsearch in PHP
查看>>
如何拦截网路突发性垃圾邮件
查看>>