Codeforces 618 D Hamiltonian Spanning Tree (思维+DFS找路径)*

A group of n cities is connected by a network of roads. There is an undirected road between every pair of cities, so there are roads in total. It takes exactly y seconds to traverse any single road.

A spanning tree is a set of roads containing exactly n - 1 roads such that it's possible to travel between any two cities using only these roads.

Some spanning tree of the initial network was chosen. For every road in this tree the time one needs to traverse this road was changed from y to x seconds. Note that it's not guaranteed that x is smaller than y.

You would like to travel through all the cities using the shortest path possible. Given n, x, y and a description of the spanning tree that was chosen, find the cost of the shortest path that starts in any city, ends in any city and visits all cities exactly once.

Input

The first line of the input contains three integers n, x and y (2 ≤ n ≤ 200 000, 1 ≤ x, y ≤ 109).

Each of the next n - 1 lines contains a description of a road in the spanning tree. The i-th of these lines contains two integers ui and vi (1 ≤ ui, vi ≤ n) — indices of the cities connected by the i-th road. It is guaranteed that these roads form a spanning tree.

Output

Print a single integer — the minimum number of seconds one needs to spend in order to visit all the cities exactly once.

Examples

Input

5 2 3
1 2
1 3
3 4
5 3

Output

9

Input

5 3 2
1 2
1 3
3 4
5 3

Output

8

Note

In the first sample, roads of the spanning tree have cost 2, while other roads have cost 3. One example of an optimal path is .

In the second sample, we have the same spanning tree, but roads in the spanning tree cost 3, while other roads cost 2. One example of an optimal path is .

#include<iostream>
#include<algorithm>
#include<string>
#include<map>//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include<set>//int gcd(int a,int b){return b?gcd(b,a%b):a;}
#include<vector>
#include<cmath>
#include<stack>
#include<string.h>
#include<stdlib.h>
#include<cstdio>
#define ll long long
#define maxn 200005
#define ms memset
using namespace std;
ll n,x,y;
ll a,b,cnt;///cnt记录者最终答案的形式
ll d[maxn],vis[maxn];
vector<ll> mp[maxn];
/*
自测数据:
8 2 3
1 2
2 8
1 3
3 4
3 5
1 6
6 7
*/
/*
题目大意:给定一个树形,和两种权值,
一种是在树中的权值,一种是在完全图中权值。

对x和y分类讨论:
如果y小,则可以观察如果给定的树形不是星型,
那么其答案就是(n-1)*y , 不然就是x+(n-2)*y;

如果x小,则要尽量把所有的路径放到给定的树中。
下面分析:在出发节点,如果下一个扩展节点,
是一个最长路径的开头或结尾,那么显然肯定能对接,扩展边计入答案。
如果是一条最佳路径的中间节点,那么再累计完那棵子树后探索边不能用,
因为不能累加计数,不然破坏题目性质。

这样,dfs的结构就出来了,dfs(u,v)在上一个节点为v,当前节点为u的dfs层搜索答案。
总答案是所有dfs块累加,外加对于探索边的检查。
*/
int dfs(ll t,ll pre)
{
    int lft=2;
    for(int i=0;i<mp[t].size();i++)
    {
        ll v=mp[t][i];
        if(v==pre) continue;
        if(dfs(v,t)&&lft>0)
        {
            lft--;
            cnt++;
          ///  cout<<v<<" "<<t<<endl;
        }
    }
    return lft>0;
}

int main()
{
    scanf("%lld%lld%lld",&n,&x,&y);

    memset(d,0,sizeof(d));
    for(int i=1;i<=n;i++) mp[i].clear();

    for(int i=0;i<n-1;i++)
    {
        scanf("%d%d",&a,&b);
        d[a]++,d[b]++;
        mp[a].push_back(b);
        mp[b].push_back(a);
    }
    ///判断是否为菊花图
    if( x>=y )
    {
        cnt=0;
        for(int i=1;i<=n;i++)
            if(d[i]==n-1) cnt=1;
        if(cnt==0) printf("%lld\n",(ll)(n-1)*y);
        else   printf("%lld\n",(ll)x+(ll)(n-2)*y);///判断是否为星状图
    }
    else
    {
        cnt=0;
        ///需要对每一个点进行dfs
        dfs(1,-1);
        printf("%lld\n",(ll)cnt*x+(ll)(n-1-cnt)*y);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/81222145