zoj 3732 构造(Havel-Hakimi)

来源:互联网 发布:个人信息网络黑市 编辑:程序博客网 时间:2024/05/16 19:37

题意 : 一个无向图,无环无重边,给出每个订点的度, 根据这些信息能确定唯一的图 就输出 给的单词 ,并且输出每条边 ,不是唯一的图 ,输出给的单词,并且输出两种的图的边的信息   如果无法确定一个图 ,输出 给的单词;


思路:Havel-Hakimi定理的应用,上一次看到这个定理已经是好久以前了,艰难的怀念起这个定理,写完以后各种wa,由于是别人给讲的题意,没仔细看题,最后发现居然是输出多解的时候少输出一组n和m,崩溃了……Havel-Hakimi定理还是蛮好理解的,可以百度一下,这样有解和无解都没问题,剩下的只有是否存在多解的问题。直觉上想,如果存在多解,那么其他解应该是一组解中的某些边进行交换得到的。再看看Havel-Hakimi定理的构造过程,按度数排序后,每次选一个度数最大的点,然后将后面的点的度数依次减1,表示该顶点和相应的顶点有边相连,重复进行上面的操作,如果有点的度数减到-1,那么说明无解。可以看出,这个构造过程每次都会满足一个顶点,这个过程有点类似于贪心,在这个过程中,如果把某两个点“互换”,那么就可以构造出多解的,那么什么样的两个点才可以互换呢,比如我现在已经排完序,要减的度数序列一直到p,这时,如果p+1的点的度数和p是相同的,那么p位置和p+1是可以"互换“的,连这两个点中的哪一个都不会影响结果……


#include<cstdio>#include<cstring>#include<map>#include<vector>#include<cmath>#include<cstdlib>#include<stack>#include<queue>#include <iomanip>#include<iostream>#include<algorithm>using namespace std ;const int N=100000;struct node{int x,id;}e[200];int a[N][2] , A,B ,top,n;bool operator<(const node &a,const node &b){    if(a.x>b.x)        return 1;        else        return 0;}int main(){while(~scanf("%d",&n)){   for(int i = 1 ; i <= n ; i++)   {       scanf("%d",&e[i].x);   e[i].id=i;    }           top = 0 ;           int k=1,f=1;//   sort(e+i,e+n+i);  //   for(int i = 1 ; i <= n ; i++) printf("%d ",e[i].x);   for(int i = 1 ; i <= n ; i++)      {       sort(e+i,e+n+1); //reverse(e+i,e+n+1);       if( e[n].x<0 || i+ e[i].x > n )                    k=0;             if(  e[i].x+i+1<=n && e[e[i].x+i].x == e[e[i].x+i+1].x && e[e[i].x+i+1].x && k==1)             {               k = 2;               A = e[e[i].x+i].id;               B = e[e[i].x+i+1].id;               f=top;             } for(int j = 1 ; j <= e[i].x ; j++){    a[top][0]=e[i].id;    a[top][1]=e[i+j].id;    e[i+j].x--;    top++;}      }      if(k==0)   {       printf("IMPOSSIBLE\n");   }   else if(k==1)   {       printf("UNIQUE\n");   }   else if(k==2)   {        printf("MULTIPLE\n");   }   if(k)   {        printf("%d %d\n",n,top);if(top) printf("%d",a[0][0]);        for(int i = 1; i < top ; i++)        {           printf(" %d",a[i][0]) ;        }         puts("");        if(top) printf("%d",a[0][1]);        for(int i = 1; i < top ; i++)        {           printf(" %d",a[i][1]) ;        }         puts("");   }   if(k==2)   {        printf("%d %d\n",n,top);        if(f) printf("%d",a[0][0]); else if(top)        {           if(a[0][0]==A)              printf("%d",B);           else if(a[0][0]==B)  printf("%d",A);   else      printf("%d",a[0][0]) ;              }        for(int i = 1 ; i < f ; i++)        printf(" %d",a[i][0]) ;        for(int i = max(f,1) ; i < top ; i++)        {           if(a[i][0]==A)              printf(" %d",B);           else if(a[i][0]==B)  printf(" %d",A);   else      printf(" %d",a[i][0]) ;        }        puts("");                if(f)  printf("%d",a[0][1]);         else if(top)        {           if(a[0][1]==A)              printf("%d",B);           else if(a[0][1]==B)  printf("%d",A);   else      printf("%d",a[0][1]) ;              }        for(int i = 1 ; i < f ; i++)        printf(" %d",a[i][1]) ;        for(int i = max(f,1) ; i < top ; i++)        {           if(a[i][1]==A)              printf(" %d",B);           else if(a[i][1]==B)  printf(" %d",A);   else      printf(" %d",a[i][1]) ;        }        puts("");           }}return 0;;}


0 0
原创粉丝点击