15安徽省赛

来源:互联网 发布:网络电话软件有哪些 编辑:程序博客网 时间:2024/05/16 01:33
15省赛解题报告

题目描述:

A First Blood

Time Limit:3000/1000 MS (Java/Others)

问题描述

盖伦是个小学一年级的学生,在一次数学课的时候,老师给他们出了一个难题:

老师给了一个正整数 n,需要在不大于n的范围内选择三个正整数(可以是相同的),使它们三个的最小公倍数尽可能的大。盖伦很想第一个解决这个问题,你能帮助盖伦拿到“first blood”吗?

输入

首先是一个正整数T,表示有T组测试数据

每组测试数据是一个正整数n(1<=n<=10^6)

输出

对于每组测试数据,输出最大的最小公倍数,每个输出单独占一行

样例输入

2

9

7

样例输出

504

210

注意事项

数据范围超出32位整数,可用longlong__int64表示64位整数

解题思路:

 

具体解法:

刚开始就是想暴力解决,设置三个变量,从大到小枚举,n的范围10^6方,肯定超时,后来查了一些关于数论的资料,了解到如下定理:两个数的最小公倍数在最大的时候就是两个数互质的时候,这时候的最小公倍数就是它们的乘积;相邻自然数是互质的。这个时候就存在两种情况:n为偶数,n为奇数。

 =1 \* ROMAN I,n为奇数时,nn-1n-2,这时候nn-2都是奇数,所以2不是这三个数其中两个数的公因子,三个数的变化范围是2,且是连续的,所以因子一定小于等于2,这就得出三个数时互质的,那么不大于n的三个数就找到了,此时最大的最小公倍数就是三个数的乘积。

 =2 \* ROMAN II,n为偶数时,可以看出,nn-1n-2,三个数中,2nn-2的公因子,这是最小公倍数就“大大”减小了,假如选择nn-1n-3,这时n-1是奇数,n-3是奇数,而且只间隔一个数,故互质,nn-3相差3,如果n能被3整除,那么3就是nn-3的公因子,这时最小公倍数“大大”减小了,那么就应该选择n-1n-2n-3,这就是n-1为奇数的时候,可参考 = 1 \* ROMAN I。当n不能被3整除的时候,三个数分别是nn-1n-3;当n3整除的时候,三个数分别是n-1n-2n-3

特别注意n=12的特殊情况。

代码实现:

#include<iostream>

#include <string.h>

using namespacestd;

int main()

{

       long long n;

       long long ta, tb;

       int t;

       cin>>t;

       while(t--)

       {

          cin>>n;

              if(n <= 2)

                     cout<<n<<endl;

              else

              {

                     if(n%2==1)

                            cout<<(n*(n-1)*(n-2))<<endl;

                     else

                     {

                         if(n%3!=0)

                             ta =n*(n-1)*(n-3);

                             else ta=0;

                            tb =(n-1)*(n-2)*(n-3);

                            if(ta>tb)

                    cout<<ta<<endl;

                elsecout<<tb<<endl;

                     }

              }

       }

       return 0;

}

运行结果:

求和

Time Limit:3000/1000 MS (Java/Others)

问题描述

对于正整数n,k,我们定义这样一个函数 本地图片,请重新上传 \* MERGEFORMAT ,它满足如下规律

本地图片,请重新上传 \* MERGEFORMAT

现在给出nk,你的任务就是要计算 本地图片,请重新上传 \* MERGEFORMAT 的值。

输入

首先是一个整数T,表示有T组数据

接下来每组数据是nk( 本地图片,请重新上传 \* MERGEFORMAT )

输出

打印出f(n,k)的值,每个输出单独占一行

样例输入

3

1 1

2 1

3 1

样例输出

-1

1

-2

解题思路:

 fnk)的定义可以看出,首先是k个减号,然后是k个加号,每k个减号和加号计算结果为k*k,只需求出有多少组,然后乘以k*k,把多余的数字减去或加上。

代码实现:

#include<iostream>

#include<algorithm>

using namespacestd;

int main()

{

    longlong t;

    cin>>t;

    while(t--)

    {

        long long n,i,j,k,a,b,f,sum=0,s;

        cin>>n>>k;

        a=n/k;

        b=a/2;

        sum=b*k*k;

        s=n-b*2*k;

        f=1+b*2*k;

        if(s<=k)

        {

            for(i=0;i<s;i++)

            {

                sum=sum-f;

                f++;

            }

        }

        else

        {

            for(i=0;i<k;i++)

            {

                sum=sum-f;

                f++;

            }

            for(i=0;i<s-k;i++)

            {

                sum=sum+f;

                f++;

            }

        }

        cout<<sum<<endl;

    }

    return 0;

}


 

C LU的困惑

Time Limit:3000/1000MS (Java/Others)

问题描述

Master Lu 非常喜欢数学,现在有个问题:在二维空间上一共有n个点,LU每连接俩个点,就会确定一条直线,对应有一个斜率。现在LU把平面上所有点中任意两点连接成一条线,并将这条线的斜率加入一个集合(若斜率不存在则不计入集合),他想知道这个集合中有多少元素。

输入

第一行是一个整数T,代表T组测试数据。

每组数据第一行是一个整数n,代表点的数量,且2<n<1000

接下来n行,每行两个整数,0<x<100000<y<10000,代表点的坐标

输出

输出斜率集合中有多少个元素

样例输入

2

4

1 1

2 2

3 3

3 6

4

1 1

2 2

2 0

3 1

样例输出

3

3

解题思路:

思路比较清晰,求出所以的斜率,求出不一样的个数就行了,这里涉及到排序,可以使用sort函数,然后我用来unique函数,可以直接求出值不相同的个数。斜率用double类型保存,还有如果两个点的x相同则不存在斜率,在求的时候要判断一下。求斜率的时间复杂度为On*n/2)。

实现代码:

#include<iostream>

#include<algorithm>

using namespacestd;

struct point

{

    double x,y;

};

point po[1005];

doublexielv[1000005];

int n;

int main()

{

   int t,i,j,ans;

   cin>>t;

   while(t--)

   {

       ans=0;

       cin>>n;

       for(i=0;i<n;i++)

        cin>>po[i].x>>po[i].y;

       for(i=0;i<n-1;i++)

        for(j=i+1;j<n;j++)

       {

           if(po[i].x!=po[j].x)

           xielv[ans++]=(po[j].y-po[i].y)/(po[j].x-po[i].x);

       }

       sort(xielv,xielv+ans);

       int d=unique(xielv,xielv+ans)-xielv;

       cout<<d<<endl;

   }

return 0;

}


 

锐雯上单不给就送

Time Limit:3000/1000 MS (Java/Others)

问题描述

《英雄联盟》(简称LOL)是由美国Riot Games发,腾讯游戏运营的英雄对战网游。《英雄联盟》除了即时战略、团队作战外,还拥有特色的英雄、自动匹配的战网平台,包括天赋树召唤师系统、符文等元素。简单来说,LOL两队的对战游戏,一个队伍(5个人)对抗另一个队伍(5个人),主要目的是拆掉对面的建筑物,一个每个队伍的英雄都扮演着不同的角色,分别为“上单”,“打野”,“中单”,“辅助”,ADC”,通常的情况是各自队伍的“上单”VS“上单”,“打野”VS“打野”,“中单”VS“中单”,“辅助”VS“辅助”,ADC”VSADC”。上单在LOL中一直是一个很吃香的角色,一般小学生进入匹配以后都会强调一句“锐雯上单不给就送”作为联络暗号。zz_1215devtang经常玩这个游戏,zz_1215devtang的宿敌,devtang很想知道zz_1215玩的什么角色,然后他就选同样的角色和zz_1215决斗(solo)。经过观察devtang发现zz_1215选择什么角色是有规律的,那就是取决于上一次他玩的什么角色。现用一个5*5的矩阵来表示, 本地图片,请重新上传 \* MERGEFORMAT 表示上一次如果zz_1215玩的是第j个角色,那么他这一次玩第i个角色的概率为 本地图片,请重新上传 \* MERGEFORMAT 本地图片,请重新上传 \* MERGEFORMAT ,另外有 本地图片,请重新上传 \* MERGEFORMAT 现在知道zz_1215第一次玩的是什么角色,devtang想知道在第n次游戏中,zz_1215最有可能玩的是什么角色。

输入

首先是一个整数T,表示有T组数据

每组数据包括

第一行是一个数字n 本地图片,请重新上传 \* MERGEFORMAT ,表示devtang想知道第n次游戏中zz_1215最可能玩的角色,

接下来会给出5*5的矩阵表示概率关系.

最后一行给出整数m( 本地图片,请重新上传 \* MERGEFORMAT )表示zz_1215第一次游戏玩的角色,角色表示方法见注意事项。

输出

输出第n次游戏中,zz_1215最有可能玩的角色,角色表示方法见注意事项,每个输出单独占一行

样例输入

2

1

0 0.1 0.2 0.3 0.4

0.4 0 0.1 0.2 0.3

0.3 0.4 0 0.1 0.2

0.2 0.3 0.4 0 0.1

0.1 0.2 0.3 0.4 0

3

2

0 0.1 0.2 0.3 0.4

0.4 0 0.1 0.2 0.3

0.3 0.4 0 0.1 0.2

0.2 0.3 0.4 0 0.1

0.1 0.2 0.3 0.4 0

3

样例输出

3

4

注意事项

1,2,3,4,5分别代表“上单”,“打野”,“中单”,“辅助”,“ADC”这五个角色,如果存在多个角色的概率相同的话,那么就选择下标最小的那个,比如经过计算13的概率都是0.5,那么zz_1215会选择1这个角色。

解题思路:

矩阵快速幂,把矩阵的个数写成二进制的形式,类似于模平方重复计算法。

代码实现:

#include<iostream>

#include<stdio.h>

#include<algorithm>

#include<string.h>

#include<cmath>

#include<ctype.h>

#include<limits>

#define INF 0x3f3f3f3f

using namespace std;

const int maxn=10;

struct matrix

{

   double m[5][5];

};

 

matrix mul(matrix a,matrix b)

{

   matrix c;

   int i,j,k;

   for(i=0;i<5;i++)

        for(j=0;j<5;j++)

        {

            c.m[i][j]=0;

           for(k=0;k<5;k++)

           c.m[i][j]+=a.m[i][k]*b.m[k][j];

        }

        return c;

}

 matrix pow_M(matrix a,int k)  //矩阵快速幂

{

    matrix ans;

    memset(ans.m,0,sizeof(ans.m));

    for (int i=0;i<5;i++)

         ans.m[i][i]=1;

    matrix temp=a;

    while(k)

    {

         if(k&1)ans=mul(ans,temp);

         temp=mul(temp,temp);

        k>>=1;

    }

    return ans;

}

int main()

{

   int t;

   cin>>t;

   while(t--)

   {

 

         int n , m;

         cin>>n ;

         int i , j ;

         matrix t ;

         for (i = 0 ; i < 5 ; i++)

             for (j = 0 ; j < 5 ; j++)

                 cin>>t.m[i][j] ;

         cin>>m ;

         if (n == 1)

         {

                 cout<<m<<endl ;

             continue ;

         }

         n-=1 ;

         m-=1 ;

         double MAX = 0 ;

         int id ;

         matrix ans = pow_M(t,n) ;

 

         for (i = 4 ; i >= 0 ; i--)

         {

             if (ans.m[i][m] > MAX ||abs(ans.m[i][m] - MAX) < 1e-6)

             {

                 MAX = ans.m[i][m] ;

                 id = i ;

             }

         }

        cout<<id+1<<endl ;

    }

   return 0;

}

 

多重部分和问题

Time Limit:30000/10000MS (Java/Others)

问题描述

n种不同大小的数字 QUOTE   本地图片,请重新上传,每种各QUOTE   本地图片,请重新上传个。判断是否可以从这些数字之中选出若干使它们的和恰好为K

输入

首先是一个正整数T(1<=T<=100)

接下来是T组数据

每组数据第一行是一个正整数n(1<=n<=100),表示有n种不同大小的数字

第二行是n个不同大小的正整数 QUOTE   本地图片,请重新上传 (1<=QUOTE   本地图片,请重新上传<=100000)

第三行是n个正整数 QUOTE   本地图片,请重新上传 (1<=QUOTE   本地图片,请重新上传<=100000),表示每种数字有 QUOTE   本地图片,请重新上传

第四行是一个正整数K(1<=K<=100000)

输出

对于每组数据,如果能从这些数字中选出若干使它们的和恰好为K,则输出“Yes”,否则输出“No”,每个输出单独占一行

样例输入

2

3

3 5 8

3 2 2

17

2

1 2

1 1

4

样例输出

Yes

No

解题思路:

dp问题,其中dp[i][j]表示前i个数能否组合成j

dp[0][0]=1;

for(inti=0;i<n;i++)

              for(int j=0;j<=K;j++)

                     for(int w=0;w<=m[i]&& w*a[i]<=j;w++)

                {

                            dp[i+1][j]=dp[i+1][j]|dp[i][j-w*a[i]];

                     }

代码实现:

#include<iostream>

#include<string.h>

using namespacestd;

int n,K;

const intmaxn=105;

const intmaxk=100005;

inta[maxn],m[maxn];

booldp[maxn][maxk];

int main()

{

    int t;

    cin>>t;

    while(t--)

    {

       cin>>n;

       for(int i=0;i<n;i++)

              cin>>a[i];

       for(int i=0;i<n;i++)

              cin>>m[i];

       cin>>K;

       memset(dp,0,sizeof(dp));

       dp[0][0]=1;

       for(int i=0;i<n;i++)

              for(int j=0;j<=K;j++)

                     for(int w=0;w<=m[i]&& w*a[i]<=j;w++)

                {

                            dp[i+1][j]=dp[i+1][j]|dp[i][j-w*a[i]];

                     }

 

       if(dp[n][K])cout<<"Yes"<<endl;

       elsecout<<"No"<<endl;

    }

       return 0;

}


 

你来擒孟获

Time Limit:3000/1000MS (Java/Others)

问题描述

三国时期,南蛮王孟获叛乱,诸葛亮起兵平乱。

当深入南蛮之地时,遇当地人绘得地图,发现各地分别由各个寨主据守,若诸葛亮想兵分多路进军,尽快占领各个山寨(必须占领所有山寨),并且最终所有士兵都汇聚到孟获所在山寨,若给你一次穿越的机会,你用程序告诉诸葛亮最少需要多少天才能完成任务。假设军队足够多,各分队行军速度一样,且诸葛亮神机妙算,到达每个山寨即日可以攻克。

输入

首先是一个正整数T,接下来是T组测试数据,每组数据第一行是两个整数n,m(2=<n<=1000,1=<m<=10000),表示山寨数量和山寨间的道路数量,山寨编号0123….n-1

接下来m行,每行三个整数i,j,k(0=<i,j<nk<=10^4),分别表示山寨i和山寨j之间有一条路,在这条路上需要行军k天,接下来一行两个整数s,t(0<=s,t<=n-1),分别表示诸葛亮所在部队的起点和孟获山寨所在终点的编号。

输出

对每组数据输出一个整数,表示诸葛亮的士兵占领所有山寨并汇聚到孟获所在山寨所需要的最少天数,每个输出独占一行

样例输入

2

5 6

0 1 2

1 2 2

3 1 2

4 0 3

3 2 3

3 4 1

4 3

5 5

1 0 1

1 2 3

1 3 3

4 2 2

3 4 1

4 2

样例输出

7

9

解题思路:

求出每个顶点到起点和终点的最短距离,每次相加取最大。使用dijkstra算法。

代码实现:

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<cmath>

using namespacestd;

#define INF0x3f3f3f3f

#define maxn 1001

int cost[maxn][maxn];

int d[maxn];

bool used[maxn];

void dijkstra(intn,int s)

 {

     memset(d,INF,sizeof(d));

     memset(used,false,sizeof(used));

     d[s]=0;

    while(true)

     {

         int v=-1;

         for(int u=0;u<n;u++)

             if(!used[u]&&(v==-1||d[u]<d[v]))

                 v=u;

         if(v==-1)

            break;

         used[v]=true;

         for(int u=0;u<n;u++)

         {

             d[u]=min(d[u],d[v]+cost[u][v]);

         }

     }

 }

 

 int main()

 {

     int T,m,n,k,i,j;

     int from,to,Cost,f,t;

     cin>>T;

     while(T--)

     {

         memset(cost,INF,sizeof(cost));

         cin>>n>>m;

         for(i=0;i<m;i++)

         {

            cin>>from>>to>>Cost;

            cost[from][to]=cost[to][from]=Cost;

         }

         cin>>f>>t;

         dijkstra(n,f);

         int Time[maxn],tim=0;

         memset(Time,0,sizeof(Time));

         for(i=0;i<n;i++)

             Time[i]=d[i];

         dijkstra(n,t);

         for(i=0;i<n;i++)

         {

             Time[i]+=d[i];

             tim=max(tim,Time[i]);

         }

         cout<<tim<<endl;

     }

     return 0;

 }

7

Time Limit:3000/1000 MS (Java/Others)

问题描述

7是一个简单的饭桌游戏,有数人围成一桌,先从任意一人开始数数,123……那样数下去,逢到7的倍数(71421……)和含有7的数字(1727……)必须以敲桌子代替。如果有谁逢7却数出来了,就要接受惩罚。小明觉得这个游戏太简单了,于是对它做出了改进,那就是每逢到素数的时候就以敲桌子代替,并且数数的方向发生改变,而且最开始的那个人可以从1 本地图片,请重新上传 \* MERGEFORMAT 中选一个合数,开始数数。假设现在有10个人,第一个人的编号为1,他选择4开始数,由于4不是素数,那么就是1:4,轮到下一个编号为2的人来数,由于5是素数,2敲桌子(duang),由于5是素数,顺序发生变化,现在又轮到1:6,然后以此类推10敲桌子(duang)1:82:9…一直到某人出现错误为止。小明想知道轮到自己的时候应该干什么,你能够帮小明解决这个问题吗?

输入

首先是一个整数T,表示有T组数据,接下来每组数据第一行会给出nm( 本地图片,请重新上传 \* MERGEFORMAT ),分别表示饭桌上有n个人,小明的编号是m,第二行会给出ab( 本地图片,请重新上传 \* MERGEFORMAT ),分别表示从编号为a的人开始,并且选择合数b开始数数

输出

输出轮到小明的时候他应该干什么,如果是说数字就把该数字输出,如果是敲桌子就输出“duang”,每个输出单独占一行

样例输入

3

10 2

3 4

3 3

2 6

4 1

3 8

样例输出

duang

duang

10

注意事项

假如从第a个人开始,如果没有改变方向,下一个人就是a+1或者1,否则就是a-1n

解题思路:

首先素数打表,打表的时候范围要比10000大,可以打表到20000,注意无论从哪个方向到了该到编号为n的同学时,模取为0,这时候判断一下,然后修改当前到达的同学的编号。

代码实现:

#include<iostream>

#include<stdio.h>

#include<algorithm>

#include<string.h>

#include<cmath>

#include<ctype.h>

#include<limits>

using namespacestd;

const intmaxn=20000;

bool prime[maxn];

voidget_prime()  

{

     int i,j;

     memset(prime,true,sizeof(prime));

     for(i=2;i<=maxn;++i)

        if(prime[i])

     {

         if(maxn/i<i)break;

         for(j=i*i;j<=maxn;j=j+i)

            prime[j]=false;

     }

}

int n,m,a,b;

void duang()

{

    int i,j;

    int flag=1,dir=1;

    int now=a,now_num=b;

    if(m==now)

        {

            cout<<now_num<<endl;

            flag=0;

        }

    else

    {

    while(now!=m)

    {

        if(prime[now_num]==true)

        {

            if(dir==1)

              {

                  now=(now-1)%n;

                   if(now==0)

                    now=n;

              }

              else

              {

                     now=(now+1)%n;

                   if(now==0)

                     now=n;

              }

              dir=-dir;

        }

        else

        {

            if(dir==1)

            {

                now=(now+1)%n;

               if(now==0)

                now=n;

            }

            else

            {

                now=(now-1)%n;

                   if(now==0)

                    now=n;

            }

        }

        now_num++;

    }

    if(flag==1)

    {

    if(prime[now_num]==true)

       cout<<"duang"<<endl;

    else cout<<now_num<<endl;

    }

    }

}

 

int main()

{

    int t;

    scanf("%d",&t);

    get_prime();

    while(t--)

    {

       scanf("%d%d%d%d",&n,&m,&a,&b);

        duang();

    }

    return 0;

}

梯田

Time Limit:3000/1000MS (Java/Others)

问题描述

土豪YZK在一块小岛上有着一大片n*m的梯田,每块1*1的梯田都有它的高度。奴隶们不甘被YZK剥削,他们联合起来决定发动一场海啸淹掉YZK的梯田,因为要留一部分给自己吃,所以他们决定至少淹掉p块田地,但是不能超过q块田地,否则会因为剩下的田地不够而把奴隶自己饿死。现在给你一个n*m的矩阵,矩阵中的元素代表梯田中每块田地的高度,求能否发动一场高度为h的海啸,满足奴隶们的要求。由于发动海啸代价很高,所以如果存在多个解,请输出最小的一个h,否则输出-1。当梯田高度及其周围8方向梯田高度均小于等于海啸高度h时,认为梯田被淹。

输入

第一行是一个正整数T,代表数据组数

对于每组数据,第一行为四个整数nmpq

之后是一个n*m的矩阵,矩阵中每个数代表每块梯田高度

1<=T<=100

1<=n,m<=100

1<=p<=q<=n*m

1<=梯田高度<=1000000

输出

对于每组数据,如果能找到h,请输出最小的h,否则输出-1

每组输出占一行

样例输入

2

3 3 3 6

1 2 3

4 5 6

7 8 9

4 4 5 6

1 2 2 1

2 1 1 2

2 1 1 2

1 2 2 1

样例输出

3

-1

实现代码:

代码实现

#include<iostream>

#include<stdio.h>

#include<string.h>

#include<cmath>

#include<algorithm>

using namespace std;

const int maxn=105;

int high[105][105],is[105][105],vis[105][105],h[maxn*maxn];

int n,m,ans,p,q;

int dfs(int i,int j,int h)

{

vis[i][j]=1;

if(high[i][j]<=h)

{

if(is[i-1][j]||is[i+1][j]||is[i][j+1]||is[i][j-1])

{

is[i][j]=1;

return 1;

}

if(high[i][j-1]<=h&&!vis[i][j-1])

dfs(i,j-1,h);

if(high[i][j+1]<=h&&!vis[i][j+1])

dfs(i,j+1,h);

if(high[i-1][j]<=h&&!vis[i-1][j])

dfs(i-1,j,h);

if(high[i+1][j]<=h&&!vis[i+1][j])

dfs(i+1,j,h);

}

else return 0;

}

int main()

{

    int t,i,j;

    scanf("%d",&t);

    while(t--)

    {

    scanf("%d%d%d%d",&n,&m,&p,&q);

    memset(is,0,sizeof(is));

    memset(high,0,sizeof(high));

    for(i=0;i<maxn;i++)

    {

    is[0][i]=1;

    is[n+1][i]=1;

}

for(j=0;j<maxn;j++)

{

is[j][0]=1;

is[j][m+1]=1;

}

int k=0;

for(i=1;i<=n;i++)

for(j=1;j<=m;j++)

{

scanf("%d",&high[i][j]);

h[k++]=high[i][j];

   }

   int ok=0;

   sort(h,h+k);

   for(int turn=0;turn<k;turn++)

   {

   for(i=1;i<=n;i++)

   for(j=1;j<=m;j++)

   dfs(i,j,h[turn]);

   ans=0;

   for(i=1;i<=n;i++)

   for(j=1;j<=m;j++)

   if(is[i][j])

   ans++;

   if(ans>=p&&ans<=q)

   {

   printf("%d\n",h[turn]);

   ok=1;

   break;

   }

   if(ok==0)

   printf("-1\n");

}

return 0;

} 



   



 

镜像树

Time Limit:3000/1000MS (Java/Others)

问题描述

一棵二叉树,若其与自己的镜像完全相同,就称其为镜像树(即这棵二叉树关于根完全对称)。例如

本地图片,请重新上传

是一棵镜像树;

本地图片,请重新上传

不是镜像树。

现给你一棵二叉树,请你判断其是不是镜像树。

输入

第一行是一个整数数T,表示测试数据有T

每组数据第一行是一个正整数n(1<=n<=100),表示二叉树中节点的数量

下面n行,每行有三个正整数ab c(1<=a<=100,0<=b,c<=100),表示以编号a的节点为父节点,它的左孩子节点编号为b,右孩子节点编号为c,若b=0表示没有左孩子节点,c=0表示没有右孩子节点,树的根节点是编号为1的节点,节点的编号都>=1(保证数据中给出的二叉树拓扑结构是合法的)

下面一行是n个正整数vi(1<=vi<=100),表示编号为i的节点的值。

输出

若数据中表示的二叉树是镜像树,输出“Yes”,否则输出“No”,每个输出单独占一行

样例输入

2

7

1 2 3

2 4 5

3 6 7

4 0 0

5 0 0

6 0 0

7 0 0

1 2 2 3 4 4 3

5

1 2 3

2 0 4

3 0 5

4 0 0

5 0 0

1 2 2 3 3

样例输出

Yes

No

解题思路:

二叉树是递归定义的,在解这题的时候,也要用到递归,只要判断三种情况,1,如果左子树为空,右子树不空,则不满足要求,直接退出;2,左子树不为空,右子树为空,直接退出;3,左右子树都不为空,但是编号不同,则退出。如果检查了所以的子树,都满足要求,则该二叉树为镜像树。

实现代码:

#include<iostream>

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<algorithm>

#include<ctype.h>

#include<queue>

#include<stack>

#include<cmath>

#include<vector>

using namespacestd;

const intMAX=1000;

int flag=1;

struct node

{

    int data;

    int lc,rc;

};

node tree[MAX];

void dfs(int i,intj)

{

    if(i==0&&j==0)

        return ;

   else if(i==0&&j!=0||(i!=0&&j==0)||(tree[i].data!=tree[j].data))

    {

        flag=0;

        return;

    }

    dfs(tree[i].lc,tree[j].rc);

    dfs(tree[i].rc,tree[j].lc);

}

int main()

{

   int t,n,a,b,c,i,j;

   cin>>t;

   while(t--)

   {

       cin>>n;

       for(i=1;i<=n;i++)

       cin>>a>>tree[i].lc>>tree[i].rc;

       for(i=1;i<=n;i++)

        cin>>tree[i].data;

       flag=1;

       dfs(tree[1].lc,tree[1].rc);

       if(flag)

       cout<<"Yes"<<endl;

       elsecout<<"No"<<endl;

   }

   return 0;

}


0 0
原创粉丝点击