zoukankan      html  css  js  c++  java
  • 2020牛客寒假算法基础集训营1 maki和tree

    https://ac.nowcoder.com/acm/contest/3002/F

    题意

      这个树有 个顶点, 条边。每个顶点被染成了白色或者黑色。
      取两个不同的点,它们的简单路径上有且仅有一个黑色点的取法有多少?
      注:
          ①树上两点简单路径指连接两点的最短路。
          ② 的取法视为同一种。

    题解

      并查集+计数。

      只经过一个黑色点的路径无非有两种,① 两端为白点,中间有一个黑点;② 任意一端是黑点。

      预处理,将每个白点的最大连通块处理出来,记录其大小。

      若一个黑点与 k 个白点相连,令 f(i) 为第 i 个白点的连通块大小()。

      则满足 ① 情况的数量为:

      满足 ② 情况的数量为:

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int N,f[maxn],link[maxn];
    string is_wb;
    vector<int> edge[maxn];
    int find(int p);
    void merge(int u,int v);
    long long cal();
    int main()
    {
       {
          fill(f,f+maxn,-1);
       }
       int i,u,v;
       scanf("%d",&N);
       cin>>is_wb;
       for(i=1;i<N;i++)
       {
          scanf("%d%d",&u,&v);
          edge[u].push_back(v);
          edge[v].push_back(u);
          if(is_wb[u-1]=='W' && is_wb[v-1]=='W')
             merge(u,v);
       }
       printf("%lld",cal());
       system("pause");
       return 0;
    }
    int find(int p)
    {
       return f[p]==-1?p:f[p]=find(f[p]);
    }
    void merge(int u,int v)
    {
       int x,y;
       x=find(u);
       y=find(v);
       if(x!=y)
       {
          f[x]=y;
          link[y]+=link[x]+1;
       }
    }
    long long cal()
    {
       int i,j;
       long long ans=0;
       for(i=1;i<=N;i++)
       {
          vector<int> v;
          vector<int> pre_v;
          v.push_back(0);
          pre_v.push_back(0);
          if(is_wb[i-1]=='W') continue;
          for(j=0;j<edge[i].size();j++)
          {
             if(is_wb[edge[i][j]-1]=='B') continue;
             v.push_back(link[find(edge[i][j])]+1);
             pre_v.push_back(link[find(edge[i][j])]+1+pre_v.back());
          }
          for(j=1;j<v.size();j++)
             ans+=v[j]*(pre_v.back()-pre_v[j]);
          ans+=pre_v.back();
       }
       return ans;
    }
  • 相关阅读:
    poj 2425 AChessGame(博弈)
    poj2975 Nim 胜利的方案数
    hdu 5724 SG+状态压缩
    hdu 5274 Dylans loves tree(LCA + 线段树)
    hdu 5266 pog loves szh III(lca + 线段树)
    hdu 4031 attack 线段树区间更新
    51 nod 1188 最大公约数之和 V2
    51nod 1040 最大公约数之和(欧拉函数)
    51nod 1035:最长的循环节
    Nim游戏(组合游戏Combinatorial Games)
  • 原文地址:https://www.cnblogs.com/VividBinGo/p/12290669.html
Copyright © 2011-2022 走看看