CF 783 F. Vlad and Unfinished Business

 

原题链接:

https://codeforces.com/contest/1675/problem/F

题目和18946 小美的送花线路 有相似之处。小美送花,只有把最远的结点最后送达才能用时最短。

题目大意:一个树结构,x是树根,要求先访问k个点(可能重复),最后访问y。

解题思路:树结构问题并不属于第五章内容,而是被看成特殊的图结构。在树结构中,如果要访问的两个点在树根的不同分支,那么(1)必须先访问一个分支,(2)返回树根后,(3)再访问另一个分支。这样第一个分支一去一回,每条边会访问两次。而最后访问的点因为无需返回树根,所以每条边只走一次。

此题目可以把y和其他k个点等同看待,只是必须把y作为最后一个访问的结点。这样答案= 所有路径长度乘以2 - y结点的深度。因为到y之后不用再返回树根了。

在dfs过程中,检查这条边是否连接任务结点,是的话就必须有去有回,总长度+2。

图的存储方法用的是邻接表写法,可参看 19085 图的存储结构(邻接表)

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int t,n,k,v[200005],x,y,ans,d[200005];/**< v数组标记任务点,d数组记录深度,其实只需要记录y深度 */
vector<int>e[200005];
int dfs(int root,int deep,int fa)
{
    d[root]=deep;/**< 只是记录深度 */
    int knum=v[root];
    for(int i=0; i<e[root].size(); i++)
        if(e[root][i]!=fa&&dfs(e[root][i],deep+1,root))/**< 如果dfs返回值不为0,说明这条边<root,e[root][i]>必须走 */
            ans+=2,knum++;/**< knum记录任务结点数量,并作为函数值返回,供上层结点判定边是否要走 */
    return knum;
}
int main()
{
    ios::sync_with_stdio(0),cin.tie(0);
    int i,j,temp,A,B;
    cin>>t;
    while(t--)
    {
        cin>>n>>k>>x>>y;
        ans=0;
        for(i=1; i<=n; i++)
            v[i]=d[i]=0,e[i].clear();
        for(i=1; i<=k; i++)
        {
            cin>>temp;
            v[temp]=1;
        }
        v[y]=1;/**< 把y也看成是任务点,但是这个点一定是最后访问 */
        for(i=1; i<n; i++)
        {
            cin>>A>>B;
            e[A].push_back(B);
            e[B].push_back(A);
        }
        dfs(x,0,0);
        cout<<ans-d[y]<<endl;/**< 走的总路径长度-y的深度 */
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值