zoukankan      html  css  js  c++  java
  • codeforces 862B Mahmoud and Ehab and the bipartiteness (DFS或带权并查集)

    B. Mahmoud and Ehab and the bipartiteness
    time limit per test
    2 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output

    Mahmoud and Ehab continue their adventures! As everybody in the evil land knows, Dr. Evil likes bipartite graphs, especially trees.

    A tree is a connected acyclic graph. A bipartite graph is a graph, whose vertices can be partitioned into 2 sets in such a way, that for each edge (u, v) that belongs to the graph, u and v belong to different sets. You can find more formal definitions of a tree and a bipartite graph in the notes section below.

    Dr. Evil gave Mahmoud and Ehab a tree consisting of n nodes and asked them to add edges to it in such a way, that the graph is still bipartite. Besides, after adding these edges the graph should be simple (doesn't contain loops or multiple edges). What is the maximum number of edges they can add?

    A loop is an edge, which connects a node with itself. Graph doesn't contain multiple edges when for each pair of nodes there is no more than one edge between them. A cycle and a loop aren't the same .

    Input

    The first line of input contains an integer n — the number of nodes in the tree (1 ≤ n ≤ 105).

    The next n - 1 lines contain integers u and v (1 ≤ u, v ≤ n, u ≠ v) — the description of the edges of the tree.

    It's guaranteed that the given graph is a tree.

    Output

    Output one integer — the maximum number of edges that Mahmoud and Ehab can add to the tree while fulfilling the conditions.

    Examples
    Input
    3
    1 2
    1 3
    Output
    0
    Input
    5
    1 2
    2 3
    3 4
    4 5
    Output
    2
    Note

    Tree definition: https://en.wikipedia.org/wiki/Tree_(graph_theory)

    Bipartite graph definition: https://en.wikipedia.org/wiki/Bipartite_graph

    In the first test case the only edge that can be added in such a way, that graph won't contain loops or multiple edges is (2, 3), but adding this edge will make the graph non-bipartite so the answer is 0.

    In the second test case Mahmoud and Ehab can add edges (1, 4) and (2, 5).

    分析:要把所有的点分成两个集合,那么最多的情况就是一个集合中所有的点都连接另一个集合中所有的点..

    需要注意的是 此时它是一个树结构也就是说所有的点都直接或间接的存在着关系

    那么当我们从一个点开始DFS的时候,奇数次的时候扫的点属于一个集合,偶数次的点属于另一个集合,这样的话,就能找出最多的边数,减去现在已有的边数就能得到答案

    DFS:

    #include <stdio.h>
    #include <algorithm>
    #include <iostream>
    #include <string.h>
    #include <queue>
    #include <vector>
    using namespace std;
    typedef long long ll;
    vector<int>V[100100];
    int vis[100100];
    ll num0;
    ll num1;
    void dfs(int x,int step)
    {
       for(int i=0;i<V[x].size();i++)
       {
           if(!vis[V[x][i]])
           {
               vis[V[x][i]]=1;
              if(step%2==1)num0++;
              else num1++;
              dfs(V[x][i],step+1);
           }
       }
    }
    int main()
    {
        int  n,a,b;
        scanf("%d",&n);
        for(int k=0;k<n-1;k++){
            num1=0;
            scanf("%d%d",&a,&b);
            V[a].push_back(b);
            V[b].push_back(a);
        }
             num0=1;
            vis[1]=1;
            dfs(1,0);
            cout<<num0*num1-(n-1)<<endl;
        return 0;
    }

     还可以从带权并查集来考虑,用0和1的权值将所有的点分成两个集合,需要注意的是每个点在最后Find操作进行,累加之后才是最后的权值

    #include <stdio.h>
    #include <algorithm>
    #include <iostream>
    #include <string.h>
    #include <queue>
    #include <vector>
    using namespace std;
    typedef long long ll;
    int F[100010];
    int val[100010];
    int Find(int x)
    {
        if(F[x]==-1)return x;
        int tmp=Find(F[x]);
        val[x]+=val[F[x]];
        val[x]%=2;
        return F[x]=tmp;
    }
    int main()
    {
       int n,a,b;
       ll num0,num1;
       scanf("%d",&n);
       memset(F,-1,sizeof(F));
       memset(val,0,sizeof(val));
       num0=0;
       num1=0;
       for(int k=0;k<n-1;k++)
       {
          scanf("%d%d",&a,&b);
          int t1=Find(a);
          int t2=Find(b);
          if(t1!=t2)
          {
            F[t2]=t1;
            val[t2]=(val[a]-val[b]+1+2)%2;
          }
             //  cout<<val[a]<<" "<<val[b]<<endl;
       }
       for(int k=1;k<=n;k++)
       {
        int  t1=Find(k);//这样才能得到该点最后的权值
        if(val[k]==0)
          num0++;
        else
           num1++;
       }
     //  cout<<num0<<" "<<num1<<endl;
       cout<<num0*num1-(n-1)<<endl;
        return 0;
    }

                    

  • 相关阅读:
    hdu 1263 水题一道
    hdu 1115 多边形重心
    hdu 4054 字符串处理
    梦想与实验:向阿里巴巴学习
    美国研究员开发电脑芯片模拟人脑工作
    阿里巴巴网站运营模式
    中文Alexa排名专业术语解释
    欧美两大3G标准正式成为我国行业标准
    网站优化的十大奇招妙技
    有志赚钱创业者 从这八个步骤开始
  • 原文地址:https://www.cnblogs.com/a249189046/p/7560208.html
Copyright © 2011-2022 走看看