拼多多2018校招—Anniversary

针对树状结构的城市和道路布局,国王希望在限定预算内最大化布置花灯的总路程。本篇介绍了通过深度优先搜索(DFS)算法来解决这一问题的方法,确保所选道路相连且不超过长度上限。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

拼多多王国的城市和道路的拓扑结构比较特别,是一个树状结构:
1. 每个城市是树的一个节点;
2. 城市之间的道路是树的一条边;
3. 树的根节点是首都。
拼多多周年庆马上就要到了,这是拼多多王国的一个大日子。为了活跃气氛,国王想在道路上布置花灯。花灯可是很贵的东西,尽管国王想要在所有道路上都布置花灯,但是如果要花太多钱的话,是过不了财政大臣那一关的。国王把这个计划告诉财政大臣,最后他们商讨出来这么一个方案:
1. 一条道路要么不布置花灯,要么整条布置花灯,不能选择其中的某一段布置;
2. 除非没有道路通向首都,否则至少为一条通向首都的道路布置花灯;

3. 所有布置花灯的道路构成的子图是连通的,这保证国王从首都出发,能通过只走布置了花灯的道路,把所有的花灯游览完; 

4. 如果某个城市(包括首都)有大于等于2条道路通向子城市,为了防止铺张浪费,最多只能选择其中的两条路布置花灯;

5. 布置花灯的道路的总长度设定一个上限。

在上述方案下,国王想要使得布置花灯的道路长度越长越好,你帮国王想想办法。

输入描述:

每个测试输入包含1个测试用例。

输入的第一行是一个正整数m,0<m<=9900,表示布置花灯的道路的总长度的上限。

输入的第二行是一个正整数n,n<=100,表示城市的个数。

紧接着是n-1行输入,每行三个正整数u、v、d,表示下标为u的城市有一条长度为d的道路通向它的一个子城市v,其中0<=u<n,0<=v<n,0<d<=100。

 

输出描述:

输出一个正整数,表示能布置花灯的道路长度的最大值

输入例子1:

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

输出例子1:

5

思路:

dfs搜索所有可能路径的长度值。包括一个节点所有的儿子中选1个儿子,选2个儿子的情况。

#include<iostream>
#include<vector>
#include<set>

using namespace std;

set<int> dfs(int root,vector<vector<int> >&sons,vector<int> &d,int m)
{
    set<int>res;
    res.insert(0);
    if(sons[root].empty())
        return res;
    vector<set<int> >st;
    
    for(auto it=sons[root].begin();it!=sons[root].end();it++)
        st.push_back(dfs(*it,sons,d,m));
    for(auto it=st.begin();it!=st.end();it++)
    {
        for(auto it1=it->begin();it1!=it->end();it1++)
        {
            if(d[sons[root][it-st.begin()]]+*it1<=m)
                res.insert(d[sons[root][it-st.begin()]]+*it1);
        }
    }
    
    for(auto it=st.begin();it!=st.end();it++)
    {
        for(auto it_1=it+1;it_1!=st.end();it_1++)
        {
            for(auto it1=it->begin();it1!=it->end();it1++)
            {
                for(auto it1_1=it_1->begin();it1_1!=it_1->end();it1_1++)
                {
                    if(d[sons[root][it-st.begin()]]+*it1+d[sons[root][it_1-st.begin()]]+*it1_1<=m)
                        res.insert(d[sons[root][it-st.begin()]]+*it1+d[sons[root][it_1-st.begin()]]+*it1_1);
                }
            }
        }
    }
    
    return res;
}



int main()
{
    int m,n;
    cin>>m;
    cin>>n;
    vector<int>father(n,-1);
    vector<int> dis(n,0);
    vector<vector<int> >sons(n);
    int u,v,d;
    for(int i=0;i<n-1;i++)
    {
        cin>>u>>v>>d;
        dis[v]=d;
        father[v]=u;
        sons[u].push_back(v);
    }
    int root=0;
    //寻找根节点
    while(father[root]!=-1 && root<n)
        root++;
    set<int>result(dfs(root,sons,dis,m));
    cout<<(result.empty()? 0:*result.rbegin())<<endl;
    return 0;

}


 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值