2019内蒙古大学生程序设计竞赛B

本文解析了2019年内蒙古大学生程序设计竞赛中的一道题目,通过构建树形结构来解决关于程序设计流程的问题,包括如何快速计算从当前阶段到达目标阶段所需的最少步骤。

2019内蒙古大学生程序设计竞赛B
Problem B
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 131072/131072K (Java/Other)
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
有的时候,题目和内容是没有一点关系的。
当然,作为一个有责任心的出题者,会把题目和名字紧紧联系在一起。
显然,小花不是一个有责任心的出题者。
由于他想尽早的完成出题任务,于是他把出题的流程抽象成了一棵树。
例如,当出完题目后,小花可以选择先写标程,或是先造数据。但找人验题,一定是在造完数据以后。
他现在正处在其中的某个阶段,你可以把所有的阶段都视为一个点。
烦人的 boss 又在催促他,并询问最快还有多久才能到第 x 个阶段。
所有的询问相互独立。
Input
第一行一个整数 T,代表 T 组数据。(T<=500)
接下来每行三个数 n,m,r。代表有 n 个阶段,m 个询问,小花现在正处在第 r 个阶段。(1<=n,m<=100000)
接下来 n-1 行,每行两个数,u,v,代表 v 阶段在 u 阶段之后。(1<=u,v<=n)
接下来一行有 m 个数,代表 boss 询问到第 x 个阶段还有多久。(1<=x<=n)
Output
对于每组数据,输出 m 个数,代表小花最快还有几步才能到要求的阶段。
如果小花已经完成了 boss 询问的那个阶段,那么对此询问输出 0。
如果无法确定小花是不是完成了那个阶段,输出-1。
如果询问的就是小花所在的阶段,输出 0。
每个询问后输出一个空格,每组数据后输出一个换行。
Sample Input

1
5 2 1
1 2
1 3
2 4
2 5
3 4

Sample Output

1 2


思路:n个节点,n-1条边,是一棵树,这题就是在一棵树上对祖先遍历更新一遍,再对子节点遍历更新一遍,然后照着题目的问题输出即可。BFS和DFS都可以。
bfs和dfs的写法都给了,注意,有的oj上使用cin和cout即使关了流也可能超时,建议使用scanf和printf读入与读出。

AC代码:

#include<bits/stdc++.h>
#define INF 0x3F3F3F3F
#define endl '\n'
#define css(n) cout<<setiosflags(ios::fixed)<<setprecision(n); 
using namespace std;
typedef long long ll;
const int maxn=1e5+50;
int n,m,r;
int t;
double a,b;
vector<int> edge[maxn];
vector<int> fa[maxn];
int dis[maxn];
void bfs1(int x)
{
    queue<int> que;
    que.push(x);
    dis[x]=0;
    while(!que.empty())
    {
        int z=que.front();
        que.pop();
        for(int i=0;i<fa[z].size();i++)
        {
            int y=fa[z][i];
            dis[y]=0;
            que.push(y);
        }    
    }
    return;
}
void bfs(int x)
{
    queue<int> que;
    dis[x]=0;
    que.push(x);
    while(!que.empty())
    {
        int z=que.front();
        que.pop();
        for(int i=0;i<edge[z].size();i++)
        {
            int y=edge[z][i];
            dis[y]=dis[z]+1;
            que.push(y);
        }
    }
    return;
}
/*void dfs1(int x)
{
    for(int i=0;i<fa[x].size();i++)
    {
        dis[i]=0;
    }
    return;
}
void dfs(int x)
{
    for(int i=0;i<edge[x].size();i++)
    {
        int y=edge[x][i];
        if(dis[y]==-1) dis[y]=dis[x]+1;
        else dis[y]=min(dis[x]+1,dis[y]);
        dfs(y);
    }
    return;
}*/
int main()
{
//    std::ios::sync_with_stdio(false);
//    cin>>t;
scanf("%d",&t);
    while(t--)
    {
        cin>>n>>m>>r;//r是小花现在的阶段
        for(int i=1;i<=n;i++)
        {
            edge[i].clear();
            fa[i].clear();
            dis[i]=-1;
        }
        n=n-1; 
        while(n--)
        {
            int a,b;
        //    cin>>a>>b;
        scanf("%d%d",&a,&b);
            edge[a].push_back(b);
            fa[b].push_back(a); 
        }
    /*    for(int i=1;i<=n;i++)
        {
            if(dis[i]==-1) bfs(i);
        }*/
        dis[r]=0;
        bfs1(r);
        bfs(r);
        while(m--)
        {
            int a;
            //cin>>a;
            scanf("%d",&a);
        //    cout<<dis[a]<<endl;
        printf("%d ",dis[a]);
        }
        printf("\n");
     } 
    return 0;
} 
### 2021 CCPC 华讯杯 内蒙古大学生程序设计竞赛题解解析 关于2021年CCPC第十六届华讯杯内蒙古大学生程序设计竞赛的题目解析或解题思路,通常可以通过以下几种方式获取相关信息: #### 官方题解与赛后总结 许多程序设计竞赛会在比赛结束后发布官方题解,这些题解通常包含了每道题目的详细解析和标准算法思路[^1]。对于2021年的CCPC华讯杯赛事,可以尝试访问CCPC官方网站或者相关的竞赛论坛寻找官方发布的题解文档。 #### 社区讨论与博客分享 除了官方渠道外,参赛选手及教练常常会在技术博客、社交媒体或编程社区(如洛谷、牛客网、优快云等)分享他们的解题经验与思路[^2]。通过搜索关键词“2021 CCPC 华讯杯 题解”,可以找到大量由参赛者撰写的解析文章。 #### 示例代码与算法实现 以下是基于常见竞赛题目类型提供的一个通用示例代码框架,用于解决可能涉及的算法问题: ```python # 示例:求解最短路径问题(Dijkstra算法) import heapq def dijkstra(graph, start): n = len(graph) dist = [float('inf')] * n dist[start] = 0 heap = [(0, start)] while heap: d, u = heapq.heappop(heap) if d > dist[u]: continue for v, w in graph[u]: if dist[v] > dist[u] + w: dist[v] = dist[u] + w heapq.heappush(heap, (dist[v], v)) return dist ``` 上述代码展示了如何使用Dijkstra算法计算图中从起点到其他所有节点的最短距离,这在许多竞赛题目中是常见的考点之一[^3]。 #### 数据结构与算法技巧 针对程序设计竞赛中的高频考点,掌握以下数据结构与算法技巧尤为重要: - 动态规划 - 贪心算法 - 图论(如最短路径、最小生成) - 字符串匹配算法(KMP、Trie) 这些知识点不仅适用于CCPC竞赛,还广泛应用于其他类似的算法竞赛中[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值