K Search for Mafuyu 详解【树(图)的遍历·带权节点】【2021-ACM-ICPC-济南站】

本文讲述了在一场ACM-ICPC比赛中解决KSearchforMafuyu问题的详细过程,涉及树形结构遍历、期望时间计算和无向图邻接表实现的AC代码。重点在于理解如何利用DFS遍历和优化数据结构以求解最小期望时间。
摘要由CSDN通过智能技术生成

刚刚打完11:00-16:00的acm-icpc济南站.这场一言难尽
1题就能铜牌,2题银牌,3题金牌2333
我们过了1题,打铁了呜呜,过的那题是 K Search for Mafuyu
题面如下
在这里插入图片描述
在这里插入图片描述
(一)题目大意
题目大意:.S中有n个房间,(n-1)对是连通的,M等概率隐藏在S的各个非1号房间中.现在K从1号房间出发,要找到M,K可以在连通的房间中移动,移动一步耗时一秒。对于每组样例,.输出最小的期望时间.
(二)思路及样例分析
n个房间呈树形结构,根节点是K的出发点即1号房间
既然M可能藏在任意房间(除1号房),那么需遍历整棵树访问每一个节点,
遍历的同时要记录每个节点到达所需的 步数
下图4个样例中.,回溯及路径已在图上标出,红色数字为每一个树的节点需要几步遍历.
红色数字求和得到期望总时间,再除以(n-1)得到期望最小时间
且模拟样例可知,遍历顺序与结果无关
在这里插入图片描述

(三)AC代码
队友写的,改了一些时间,最后把邻接表的ne[N],e[N]数组开到ne[2N],e[2N]才对的2333
大致就是 邻接表建无向图,dfs遍历每个节点,同时维护每个节点的步数

#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <cstring>
//#include <set>
//#include <list>
//#include <unordered_set>
//#include <unordered_map>
//
//#define gcd __gcd
//#define LL long long

using namespace std;

const int N = 100 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

int h[N],ne[2*N],e[2*N],st[N],w[N];
int idx;
int sum;
int n,d;
int ans;
void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

void dfs(int num)
{
 	if(sum==n)
 		return;
    
    for(int i=h[num];i!=-1;i=ne[i])
    {
     
        if(!st[e[i]]){
            st[e[i]] = 1;
            sum ++;
            w[e[i]] = d+1;
            d++;
            ans += d;
            dfs(e[i]);
            d++;
        }
    }
}

int main()
{
    ios::sync_with_stdio(false);
    
    int tt;
    scanf("%d",&tt);
    while(tt--)
    {
        scanf("%d",&n);
        idx = 0,d = 0;
        for(int i=0;i<=n;i++)h[i] = -1,st[i] = 0;
        sum = 0;
        ans = 0;
        for(int i=1;i<n;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
   			add(b,a);
   			//无向图加2次
            add(a,b);
        }
        
        st[1] = 1;
        w[1] = 0;
        sum ++;
        dfs(1);
  
//  for(int i=1;i<=n;i++)
//  {
//   cout << w[i] << " ";
//  }
//  cout << endl;
//  for(int i=0;i<idx;i++)cout << e[i] << " ";
//  cout << endl;
        
//        for(int i=1;i<=n;i++)
//        {
//            ans += w[i];
//        }
        // ans = ans / (n-1);
//        cout << ans << endl;
        double res = (double)ans;
        printf("%.10lf\n",res/(n-1));
    }
    return 0;
}
  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值