pintia---深入虎穴、小字辈、彩虹瓶、分而治之

L2-031 深入虎穴 (25分)

著名的王牌间谍 007 需要执行一次任务,获取敌方的机密情报。已知情报藏在一个地下迷宫里,迷宫只有一个入口,里面有很多条通路,每条路通向一扇门。每一扇门背后或者是一个房间,或者又有很多条路,同样是每条路通向一扇门…… 他的手里有一张表格,是其他间谍帮他收集到的情报,他们记下了每扇门的编号,以及这扇门背后的每一条通路所到达的门的编号。007 发现不存在两条路通向同一扇门。

内线告诉他,情报就藏在迷宫的最深处。但是这个迷宫太大了,他需要你的帮助 —— 请编程帮他找出距离入口最远的那扇门。

输入格式:
输入首先在一行中给出正整数 N(<10
​5
​​ ),是门的数量。最后 N 行,第 i 行(1≤i≤N)按以下格式描述编号为 i 的那扇门背后能通向的门:

K D[1] D[2] … D[K]
其中 K 是通道的数量,其后是每扇门的编号。

输出格式:
在一行中输出距离入口最远的那扇门的编号。题目保证这样的结果是唯一的。

输入样例:
13
3 2 3 4
2 5 6
1 7
1 8
1 9
0
2 11 10
1 13
0
0
1 12
0
0
输出样例:
12

bfs
还差一个测试点。。
这个测试点是当只有一个门的时候 初始编号应该设置成1:v=1

错的代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
vector <int>q[100100];
int book[100005];
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1; i<=t; i++)
    {
        int k;
        scanf("%d",&k);
        for(int j=0; j<k; j++)
        {
            int x;
            scanf("%d",&x);
            book[x]=1;
            q[i].push_back(x);
        }
    }
    int door=0;
    for(int i=1;i<=t;i++)
    {
        if(book[i]!=1)
            door=i;
    }
    int fr=0,be=0;
    int bf[100010]= {0};
    int road[100010]= {0};
    bf[fr++]=door;
    road[door]=0;
    while(fr>be)
    {
        int n=q[bf[be]].size();
        for(int i=0; i<n; i++)
        {
            bf[fr++]=q[bf[be]][i];
            road[bf[fr-1]]=road[be]+1;
        }
        be++;
    }
    int maxx=0,v=0;
    for(int i=1; i<=t; i++)
    {
        if(maxx<road[i])
        {
            maxx=road[i];
            v=i;
        }
    }
    printf("%d\n",v);
    return 0;
}

测试点都过了:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
vector <int>q[100100];
int book[100005];
int main()
{
    int t;
    scanf("%d",&t);
    for(int i=1; i<=t; i++)
    {
        int k;
        scanf("%d",&k);
        for(int j=0; j<k; j++)
        {
            int x;
            scanf("%d",&x);
            book[x]=1;
            q[i].push_back(x);
        }
    }
    int door=0;
    for(int i=1;i<=t;i++)
    {
        if(book[i]!=1)
            door=i;
    }
    int fr=0,be=0;
    int bf[100010]= {0};
    int road[100010]= {0};
    bf[fr++]=door;
    road[door]=0;
    while(fr>be)
    {
        int n=q[bf[be]].size();
        for(int i=0; i<n; i++)
        {
            bf[fr++]=q[bf[be]][i];
            road[bf[fr-1]]=road[be]+1;
        }
        be++;
    }
    int maxx=0,v=1;
    for(int i=1; i<=t; i++)
    {
        if(maxx<road[i])
        {
            maxx=road[i];
            v=i;
        }
    }
    printf("%d\n",v);
    return 0;
}

L2-026 小字辈 (25分)

本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。

输入格式:
输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。一行中的数字间以空格分隔。

输出格式:
首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。

输入样例:
9
2 6 5 5 -1 5 6 4 7
输出样例:
4
1 9

超时的代码:

这是直接将父辈直接存到子辈数组里然后 dfs,祖先存为1
dfs那里加了点 递归/递推

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int q[100005];
int bei[100005]={0};
int dfs(int x)
{
    if(q[x]==-1) return bei[x]=1;
    else{
           return bei[x]=dfs(q[x])+1;
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
    }
    int maxx=1;
    for(int i=1;i<=n;i++)
    {
        dfs(i);
        maxx=max(bei[i],maxx);
    }
    printf("%d\n",maxx);
    int k=0;
    for(int i=1;i<=n;i++)
    {
        if(maxx==bei[i])
        {
            k++;
           if(k==1) printf("%d",i);
           else printf(" %d",i);
        }
    }
    printf("\n");
    return 0;
}

最开始敲的时候想了想路径压缩,但忘了咋搞了
超时之后 试着搞了搞,嘿 AC了
AC代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int q[100005];
int bei[100005]={0};
int dfs(int x)
{

    if(bei[x]!=0) return bei[x]; //这里!!! 加了这行之后就不超时了!!!
    if(q[x]==-1) return bei[x]=1;
    else{
           return bei[x]=dfs(q[x])+1;
    }
}

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&q[i]);
    }
    int maxx=1;
    for(int i=1;i<=n;i++)
    {
        dfs(i);
        maxx=max(bei[i],maxx);
    }
    printf("%d\n",maxx);
    int k=0;
    for(int i=1;i<=n;i++)
    {
        if(maxx==bei[i])
        {
            k++;
           if(k==1) printf("%d",i);
           else printf(" %d",i);
        }
    }
    printf("\n");
    return 0;
}

L2-032 彩虹瓶 (25分)

#include <iostream>
#include <bits/stdc++.h>
#include <algorithm>

using namespace std;

int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    while(k--)
    {
        int f=0;
        int qu[1005],num=0;
        int now=1,st=0;
        for(int i=0; i<n; i++)
        {
            int x;
            scanf("%d",&x);
            if(x!=now)
            {
                if(qu[st]!=now||st==0)
                {
                    qu[++st]=x;
                    num++;
                }
                else if(qu[st]==now)
                {
                    while(qu[st]==now)
                    {
                        now++;
                        num--;
                        st--;
                    }
                    qu[++st]=x;
                    num++;
                }
            }
            else now++;

            if(num>m)
            {
                f=1;
            }
        }
        if(now!=n+1)
        {
            while(now==qu[st])
            {
                now++;
                st--;
                num--;
            }
        }
        if(now!=n+1||f==1) printf("NO\n");
        else printf("YES\n");
    }

    return 0;
}

这俩代码其实是一个意思。。。

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    while(k--)
    {
        int cnt=0,st[1005],top=0;
        int f=0,col=1;
        for(int i=1;i<=n;i++)
        {
            int x;
            scanf("%d",&x);
            if(x!=col)
            {
                cnt++;
                st[top++]=x;
            }
            else
            {
                col++;
                if(st[top-1]==col)
                {
                    while(st[top-1]==col)
                    {
                        col++;
                        cnt--;
                        top--;
                    }
                }
            }
            if(cnt>m) f=1;
        }
        if(col!=n+1)
        {
            if(st[top-1]==col)
            {
                cnt--;
                top--;
                col++;
            }
        }
        if(col!=n+1||f==1) printf("NO\n");
        else printf("YES\n");
    }

    return 0;
}

L2-025 分而治之 (25分)

用vector存图,缩小内存
vector <int> v[10001];

#include <bits/stdc++.h>
using namespace std;
vector<int>v[10001];
int n,m;
int book[10001];
bool cmp(int n)
{
   int i,j;
   for(i=1;i<=n;i++)
   {
      for(j=0;j<v[i].size();j++)
      {
         if(!book[i]&&!book[v[i][j]])//被遍历到的城市如果没有被标记并且他还有连接的城市,那么方案就不可行
         {
             return false;
         }
      }
   }
   return true;
}
int main()
{
    cin>>n>>m;
    int a,b;
    while(m--)
    {
       cin>>a>>b;
       v[a].push_back(b);
       v[b].push_back(a);
    }
    int k;
    cin>>k;
    int i;

    while(k--)
    {
        int np;
        cin>>np;
        int city;
        memset(book,0,sizeof(book));
        for(i=0;i<np;i++)
        {
           cin>>city;
           book[city]=1;
        }
        if(cmp(n)==true)
        {
           printf("YES\n");
        }
        else
        {
           printf("NO\n");
        }
    }
    return 0;
}

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页