p2701_树的构造stl版.cpp

来自「高手写的所有acm例程 在acm.zju.edu.cn 上的题目的例程」· C++ 代码 · 共 86 行

CPP
86
字号
#include <stdio.h>
#include <algorithm>
#include <utility>
#include <set>
#define MAXN   300
#define MAXM   30000

using namespace std;

typedef  pair <int,int> TQueue;
typedef  set < TQueue > TEdge;

int      N , M , dis [MAXN] [MAXN] , QSize , Father [MAXM] , RootSon;
TQueue   Queue [MAXN] , Edge [MAXM];
TEdge    EdgeSet;

bool   init ();
void   print ();
bool   Refresh ( int );

main ()
{
     int    i;
     while ( init () ) {
           for ( RootSon = 0 , i = 1; i < N; i ++ ) if ( !Refresh ( i ) ) break;
           if ( i >= N ) print ();
           else printf ( "-1\n" );
           printf ( "\n" );
     }
}

bool Refresh ( int p )
{
     
     int     a , b , c , d , i , j , r;
     
     QSize = 1 , Queue [0].first = dis [0] [p] , Queue [0].second = 0;
     
     for ( i = 1; i < p; i ++ ) {
         a = dis [0] [i] , b = dis [i] [p] , c = dis [0] [p];
         if ( a >= b + c || b >= a + c || c >= a + b || ( a + b + c ) % 2 ) return false;
         d = ( a + b - c ) / 2;
         for ( r = i , j = 0; j < d; j ++ ) r = Father [r];
         Queue [QSize].first = b - d , Queue [QSize ++].second = r;
     }
     
     sort ( Queue , Queue + QSize );
     if ( Queue [0].first == 0 ) return false;
     if ( Queue [0].second == 0 ) RootSon ++;
     
     for ( j = 1 , r = p; j < Queue [0].first; j ++ , r = Father [r] )
         Father [r] = M ++;
     Father [r] = Queue [0].second;
     
     for ( r = p , d = i = 0; i < QSize; i ++ ) {
         for ( ; d < Queue [i].first; d ++ ) r = Father [r];
         if ( r != Queue [i].second ) return false;
     }
     return RootSon <= 1;
}

void print ()
{
     TQueue            Tmp;
     TEdge :: iterator Iter;
     printf ( "%d\n" , M );
     EdgeSet.clear ();
     for ( int i = 1; i < M; i ++ ) {
         Tmp.first = i + 1 , Tmp.second = Father [i] + 1;
         if ( Tmp.first > Tmp.second ) swap ( Tmp.first , Tmp.second );
         EdgeSet.insert ( Tmp );
     }
     for ( Iter = EdgeSet.begin (); Iter != EdgeSet.end (); Iter ++ )
         printf ( "%d %d\n" , Iter->first , Iter->second );
}

bool init ()
{
     if ( scanf ( "%d" , &N ) != 1 ) return false;
     for ( int i = 0; i < N; i ++ )
         for ( int j = 0; j < N; j ++ )
             scanf ( "%d" , &dis [i] [j] );
     M = N;
     return true;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?