• 【APIO2018】铁人两项


    题面

    https://www.luogu.org/problem/P4630

    题解

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #define ri register int
    #define LL long long
    #define N 200500
    #define M 250000
    using namespace std;
    
    inline int read() {
      int f=0,ret=0; char ch=getchar();
      while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
      while (ch>='0'&& ch<='9') ret=ret*10+(ch-'0'),ch=getchar();
      return f?-ret:ret;
    }
    
    int n,m,tn;
    LL ans=0;
    
    struct tree {
      vector<int> to[N];
      LL s1[N],s2[N]; LL siz[N];
      void add_edge(int a,int b) {
        //printf("%d %d
    ",a,b);
        to[a].push_back(b);
        to[b].push_back(a);
      }
      void tonji(int x,int ff,int &tot) {
        if (x<=tn) tot++;
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (y==ff) continue;
          tonji(y,x,tot);
        }
      }
      void dp(int x,int ff,int pa,int tot) {
        siz[x]=(x<=tn);
        for (ri i=0;i<to[x].size();i++) {
          if (to[x][i]==ff) continue;
          dp(to[x][i],x,pa,tot);
          siz[x]+=siz[to[x][i]];
        }
        if (x>tn) {
          s1[x]=0LL;
          s2[x]=0LL;
          for (ri i=0;i<to[x].size();i++) {
            if (to[x][i]==ff) continue;
            s1[x]+=siz[to[x][i]];
            s2[x]+=siz[to[x][i]]*siz[to[x][i]];
          }
          s1[x]+=(tot-siz[x]);
          s2[x]+=(tot-siz[x])*(tot-siz[x]);
        }
      }
      void getans(int x,int ff,int pa) {
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (y==ff) continue;
          getans(y,x,pa);
        }
        if (x<=tn) {
          s1[x]=0LL;
          s2[x]=0LL;
          for (ri i=0;i<to[x].size();i++) {
            s1[x]+=s1[to[x][i]];
            s2[x]+=s2[to[x][i]];
          }
          for (ri i=0;i<to[x].size();i++) {
            if (to[x][i]==ff) continue;
            s1[x]-=(siz[pa]-siz[to[x][i]]);
            s2[x]-=(siz[pa]-siz[to[x][i]])*(siz[pa]-siz[to[x][i]]);
          }
          if (x!=pa) {
            s1[x]-=siz[x];
            s2[x]-=siz[x]*siz[x];
          }
          ans+=(s1[x]*s1[x]-s2[x])/2;
        }
      }
    } T;
    
    struct graph {
      vector<int> to[N];
      int clo,top;
      int dfn[N],low[N];
      int S[N];
      void add_edge(int u,int v) {
        to[u].push_back(v);
        to[v].push_back(u);
      }
      void tarjan(int x) {
        dfn[x]=low[x]=++clo; S[++top]=x;
        for (ri i=0;i<to[x].size();i++) {
          int y=to[x][i];
          if (dfn[y]) {
            low[x]=min(low[x],dfn[y]);
          }
          else {
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if (low[y]>=dfn[x]) {
              ++n;
              T.add_edge(x,n);
              int t;
              do {
                t=S[top--];
                T.add_edge(t,n);
              }
              while (t!=y);
            }
          }
        }
      }
    } G;
    
    int main(){
      tn=n=read(); m=read();
      for (ri i=1;i<=m;i++) {
        int u=read(),v=read();
        G.add_edge(u,v);
      }
      for (ri i=1;i<=tn;i++) if (!G.dfn[i]) {
        G.tarjan(i);
        int tot=0;
        T.tonji(i,i,tot);
        T.dp(i,i,i,tot);
        T.getans(i,i,i);
      }
      printf("%lld
    ",ans*2);
    }
  • 相关阅读:
    MySQL:procedure, function, cursor,handler
    Spring:ApplicationContext (2)
    Dojo: Quick Start
    Linux:常用命令
    Squirrel: 通用SQL、NoSQL客户端
    湖南师范大学邮箱申请及
    一文读懂基因测序技术的前世今生
    一 二 三代测序技术
    浅议基因测序技术的代际:后记
    浅议基因测序技术的代际
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11278534.html
Copyright © 2020-2023  润新知