zoj3732(度序列判断是否可图且是否唯一)

123 篇文章 0 订阅
46 篇文章 0 订阅

Graph Reconstruction

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 410    Accepted Submission(s): 1


Problem Description
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 contains N integers in which the i th item is the degree of i th vertex and each degree is between 0 and N-l(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 deduce any graph, just output "IMPOSSIBLE". The output format of graph is as follows:
N E
u1 u2 ... uE
v1 v2 ... vE
Where N is the number of vertices and E is the number of edges, and {ui,vi} is the i th edge of 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 3 4 2 IMPOSSIBLE

声明:此题在杭电千万别提交!杭电discuss里说这题不是spj……!!!!


题意:给出一个度序列,让你判断能否构建原图且判断原图是否唯一。

思路:构建原图好判断,关键在判断是否唯一,我的想法判断两条边能否交换位置,网上的思路是进行贪心建图的时候判断是否最后一个点p点与p+1点的度数相等,如果相等则至少存在两种建图方式。气人的是hdu未能使用spj!!怎么交怎么wa……


//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<map>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
struct data
{
    int du,id;
} a[110],b[110];
bool cmp(data a,data b)
{
    return a.du>b.du;
}
int ans1[10000000],ans2[10000000];
int tu[1100][1100];
int bj,one;
/*bool Havel_Hakimi(int n,data *arr)
{
    for(int i=0; i<n-1; ++i)
    {
        sort(arr+i,arr+n,cmp);
        if(i+arr[i].du>= n) return false;
        for(int j=i+1; j<=i+arr[i].du ; j++)
        {
            --arr[j].du;
            if(arr[j].du < 0) return false;
            ans1[bj]=arr[i].id;
            ans2[bj++]=arr[j].id;
            tu[arr[i].id][arr[j].id]=tu[arr[j].id][arr[i].id]=1;
        }
    }
    if(arr[n-1].du!=0)return false;
    return true;
}*/
bool judge(int n)
{
    sort(a,a+n,cmp);
    one=1;
    for(int k = 0; k <n; ++k)
    {
        sort(a+k,a+n,cmp);
        if(a[k].du > n - k)
            return false;
        if(!a[k].du)break;
        if(one&&(k+a[k].du+1<n)&&(a[k+a[k].du].du==a[k+a[k].du+1].du))
            one=0;
        for(int j = 1; j <= a[k].du; ++j)
        {
            if(--a[k+j].du < 0) return false;
            tu[a[k].id][a[k+j].id] = tu[a[k+j].id][a[k].id]=1;
            ans1[bj]=a[k].id;
            ans2[bj++]=a[k+j].id;
        }
    }
    return true;
}
bool judge2(int n)
{
    int ff=0;
    sort(b,b+n,cmp);
    for(int k = 0; k <n; ++k)
    {
        sort(b+k,b+n,cmp);
        if(b[k].du > n - k)
            return false;
        if(!b[k].du)break;
        if(!ff&&(k+b[k].du+1<n)&&(b[k+b[k].du].du==b[k+b[k].du+1].du))
        {
            //cout<<b[k+b[k].du].id<<"   "<<b[k+b[k].du+1].id<<endl;
            int id=b[k+b[k].du].id;
            b[k+b[k].du].id=b[k+b[k].du+1].id;
            b[k+b[k].du+1].id=id;
            ff=1;
        }
        for(int j = 1; j <= b[k].du; ++j)
        {
            if(--b[k+j].du < 0) return false;
            ans1[bj]=b[k].id;
            ans2[bj++]=b[k+j].id;
        }
    }
    return true;
}
/*int Havel(int n)
{
    int i,j;
    for(i=0; i<n; i++)
    {
        sort(a+i,a+n,cmp);//每次都要排序
        j=a[i].id;//记录头的坐标
        int v=a[i].du;
        if(v>n-i-1)//如果该点的度超过剩下的数 则不存在图
        {
            return 0;
        }
        for(int k=1; k<=v; k++) //开始减度
        {
            int x=a[k+i].id;
            a[k+i].du--;
            if(a[k+i].du<0)return 0;//为负数时2无图
            tu[j][x]=tu[x][j]=1;
            ans1[bj]=j;
            ans2[bj++]=x;
        }
    }
    return 1;
}
*/
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(tu,0,sizeof(tu));
        int sum=0;
        for(int i=0; i<n; i++)
        {
            scanf("%d",&a[i].du);
            b[i].du=a[i].du;
            b[i].id=a[i].id=i+1;
            sum+=a[i].du;
        }
        if(sum&1)
            puts("IMPOSSIBLE");
        else
        {
            bj=0;
            bool flag=judge(n);
            if(!flag)
                puts("IMPOSSIBLE");
            else
            {
                if(one)
                {
                    puts("UNIQUE");
                    printf("%d %d\n",n,sum/2);
                    for(int i=0; i<bj; i++)
                        if(i==0)
                            printf("%d",ans1[i]);
                        else printf(" %d",ans1[i]);
                    puts("");
                    for(int i=0; i<bj; i++)
                        if(i==0)
                            printf("%d",ans2[i]);
                        else
                            printf(" %d",ans2[i]);
                    puts("");
                }
                else
                {
                    puts("MULTIPLE");
                    printf("%d %d\n",n,sum/2);
                    for(int i=0; i<bj; i++)
                        if(i==0)
                            printf("%d",ans1[i]);
                        else printf(" %d",ans1[i]);
                    puts("");
                    for(int i=0; i<bj; i++)
                        if(i==0)
                            printf("%d",ans2[i]);
                        else
                            printf(" %d",ans2[i]);
                    puts("");
                    bj=0;
                    judge2(n);
                    printf("%d %d\n",n,sum/2);
                    for(int i=0; i<bj; i++)
                        if(i==0)
                            printf("%d",ans1[i]);
                        else printf(" %d",ans1[i]);
                    puts("");
                    for(int i=0; i<bj; i++)
                        if(i==0)
                            printf("%d",ans2[i]);
                        else
                            printf(" %d",ans2[i]);
                    puts("");
                }
            }
        }
    }
    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值