zoukankan      html  css  js  c++  java
  • luogu 4630 [APIO2018] Duathlon 铁人两项

    题目大意:

    无向图上找三个点 a b c使存在一条从a到b经过c的路径

    求取这三个点的方案数

    思路:

    建立圆方树

    这个圆方树保证没有两个圆点相连或两个方点相连

    对于每个节点x 设该节点为路径的中间节点

    则a c要么同在一个子树内 要么一个在子树内另一个在子树外 最后对答案<<1

    对于每个方点设val[x] 为该点所连圆点的个数

    每个方点按照两种情况算出答案之后

    用圆点减去算重的部分

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #define ll long long
    10 #define inf 2139062143
    11 #define MAXN 100100
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 int n,m,fst[MAXN],cnt,nxt[MAXN<<2],to[MAXN<<2];
    21 int st[MAXN],top,dfn[MAXN],low[MAXN],stp,sz[MAXN<<1],val[MAXN<<1],sumsz;
    22 ll ans=0;
    23 void add(int u,int v) {nxt[++cnt]=fst[u],fst[u]=cnt,to[cnt]=v;}
    24 vector<int>son[MAXN<<1];
    25 inline void tarjan(int x,int fa)
    26 {
    27     dfn[x]=low[x]=++stp,st[++top]=x;
    28     sz[x]=1,val[x]=-1;int now=0;
    29     for(int i=fst[x];i;i=nxt[i])
    30         if(!dfn[to[i]])
    31         {
    32             tarjan(to[i],x);low[x]=min(low[x],low[to[i]]);
    33             if(low[to[i]]<dfn[x]) continue;val[++m]=1;
    34             do{now=st[top--],son[m].push_back(now),sz[m]+=sz[now],val[m]++;}
    35             while(now!=to[i]);
    36             son[x].push_back(m);sz[x]+=sz[m];
    37         }
    38         else low[x]=min(low[x],dfn[to[i]]);
    39 }
    40 void dfs(int x,int tot)
    41 {
    42     int tmp= x<=n;
    43     for(int i=0;i<son[x].size();i++)
    44     {
    45         dfs(son[x][i],tot);ans+=(ll)tmp*sz[son[x][i]]*val[x];tmp+=sz[son[x][i]];
    46     }
    47     ans+=(ll)sz[x]*(tot-sz[x])*val[x];
    48 }
    49 int main()
    50 {
    51     n=read(),m=read();int a,b;
    52     while(m--){a=read(),b=read();add(a,b);add(b,a);}
    53     m=n;
    54     for(int i=1;i<=n;i++)
    55         if(!dfn[i]){tarjan(i,0);dfs(i,sz[i]);}
    56     printf("%lld
    ",ans<<1);
    57 }
    View Code
  • 相关阅读:
    【深入学习MySQL】MySQL的索引结构为什么使用B+树?
    【Python爬虫】爬了七天七夜,终于爬出了博客园粉丝数排行榜!
    【BAT面试题系列】面试官:你了解乐观锁和悲观锁吗?
    深入学习MySQL事务:ACID特性的实现原理
    深入学习Redis(5):集群
    深入学习Redis(4):哨兵
    谈谈微信支付曝出的漏洞
    深入学习Redis(3):主从复制
    深入学习Redis(2):持久化
    Spring中获取request的几种方法,及其线程安全性分析
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9349717.html
Copyright © 2011-2022 走看看