zoukankan      html  css  js  c++  java
  • Codeforces Round #397 by Kaspersky Lab and Barcelona Bootcamp (Div. 1 + Div. 2 combined) E. Tree Folding 拓扑排序

    E. Tree Folding

    题目连接:

    http://codeforces.com/contest/765/problem/E

    Description

    Vanya wants to minimize a tree. He can perform the following operation multiple times: choose a vertex v, and two disjoint (except for v) paths of equal length a0 = v, a1, ..., ak, and b0 = v, b1, ..., bk. Additionally, vertices a1, ..., ak, b1, ..., bk must not have any neighbours in the tree other than adjacent vertices of corresponding paths. After that, one of the paths may be merged into the other, that is, the vertices b1, ..., bk can be effectively erased:

    Help Vanya determine if it possible to make the tree into a path via a sequence of described operations, and if the answer is positive, also determine the shortest length of such path.

    Input

    The first line of input contains the number of vertices n (2 ≤ n ≤ 2·105).

    Next n - 1 lines describe edges of the tree. Each of these lines contains two space-separated integers u and v (1 ≤ u, v ≤ n, u ≠ v) — indices of endpoints of the corresponding edge. It is guaranteed that the given graph is a tree.

    Output

    If it is impossible to obtain a path, print -1. Otherwise, print the minimum number of edges in a possible path.

    Sample Input

    6
    1 2
    2 3
    2 4
    4 5
    1 6

    Sample Output

    3

    Hint

    题意

    给你一棵树,可以在这棵树上进行若干次操作,每次操作可以把两条相同的链,根据一个中点合并在一起,具体看题目的图片(CF上面)

    然后问你经过若干次合并之后,最后的最短链长度是多少。

    如果不能合并成一条链,输出-1.

    题解:

    拓扑排序,每次我们从度数为1的点出发bfs。

    然后往上合并,如果遇到交叉点,我们就合并链。

    我们用一个set来合并就好了,如果两条链长度一样,在set里面自动就合并了。

    显然能够bfs的点的set里面只有一个数。

    而且只能有一个点的set里面有两个数。

    最后扫一遍check一下就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 2e5+7;
    vector<int> E[maxn];
    int n,vis[maxn],len[maxn],de[maxn],d[maxn];
    set<int> S[maxn];
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            E[a].push_back(b);
            E[b].push_back(a);
            d[a]++;
            d[b]++;
        }
        queue<int> Q;
        for(int i=1;i<=n;i++){
            if(E[i].size()==1){
                Q.push(i);
                S[i].insert(0);
            }
        }
        while(!Q.empty()){
            int now = Q.front();
            vis[now]=1;
            Q.pop();
            for(int i=0;i<E[now].size();i++){
                int v = E[now][i];
                if(vis[v])continue;
                S[v].insert((*S[now].begin())+1);
                d[v]--;
                if(d[v]==1&&S[v].size()==1){
                    Q.push(v);
                }
            }
        }
        int ans = 0,num2 = 0;
        for(int i=1;i<=n;i++){
            if(S[i].size()==0){
                cout<<"-1"<<endl;
                return 0;
            }
            if(S[i].size()>2){
                cout<<"-1"<<endl;
                return 0;
            }
            if(S[i].size()==1){
                ans=max(ans,*S[i].begin());
            }
            if(S[i].size()==2){
                ans=max(ans,*S[i].begin()+*S[i].rbegin());
                num2++;
            }
        }
        if(num2>1){
            cout<<"-1"<<endl;
            return 0;
        }
        while(ans%2==0){
            ans/=2;
        }
        cout<<ans<<endl;
    }
  • 相关阅读:
    Eclipse正确导入第三方project
    面试的基础_01字符串反向操作
    一个简单的实现了智能虚拟女友—图灵机器人
    Notepad++去除代码行号的几种方法
    fastjson将bean转成字符串时首字母变小写问题
    2015第34周二能收发邮件但不能打开网页解决方法
    2015第34周一
    2015第33周日
    2015第33周六
    构建自己的顾问团
  • 原文地址:https://www.cnblogs.com/qscqesze/p/6401615.html
Copyright © 2011-2022 走看看