zoukankan      html  css  js  c++  java
  • 【JZOJ4784】【NOIP2016提高A组模拟9.15】Map

    题目描述

    这里写图片描述

    输入

    这里写图片描述

    输出

    这里写图片描述

    样例输入

    4 4 2
    1 2
    2 3
    3 2
    3 4
    1 2
    1 4

    样例输出

    14

    数据范围

    这里写图片描述

    样例解释

    upd:保证原图连通。
    “不相交路径”的定义为不存在相同的边。可以存在相同的点。重边视为不同的边。
    对于样例:
    原图有2个安全点对为(2,3),(3,2)
    询问1答案为4,新增的安全点对为(1,2),(1,3),(2,1)(3,1)
    询问2答案为10,新增的安全点对为(1,2),(1,3),(1,4),(2,1)(2,4),(3,1),(3,4),(4,1),(4,2),(4,3)
    因此输出14

    解法

    利用边双连通分量缩点,再利用lca统计答案。

    代码

    #include<iostream>
    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    #include<algorithm>
    #define ll long long
    #define ln(x,y) (ll)(log(x)/log(y))
    #define sqr(x) ((x)*(x))
    using namespace std;
    const char* fin="aP3.in";
    const char* fout="aP3.out";
    const ll inf=0x7fffffff;
    const ll maxn=400007,maxm=maxn*4,maxk=22;
    ll n,m,t,i,j,k,l,tot,limit,tmp,cnt;
    ll fi[maxn],ne[maxm],la[maxm],de[maxn];
    ll fa[maxn][maxk],sum[maxn][maxk],qsum[maxn][maxk];
    ll dfn[maxn],low[maxn],num,stack[maxn],blg[maxn];
    ll az[maxn];
    ll ans;
    bool bz[maxn],cz[maxn],dz[maxn];
    ll read(){
        ll x=0;
        char ch=getchar();
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
        return x;
    }
    void add_line(ll a,ll b){
        tot++;
        ne[tot]=fi[a];
        la[tot]=b;
        fi[a]=tot;
    }
    void dfs(ll v,ll from){
        ll i,j,k;
        cz[v]=true;
        fa[v][0]=from;
        qsum[v][0]=sqr(sum[v][0]);
        de[v]=de[from]+1;
        for (i=1,j=ln(de[v],2);i<=j;i++){
            k=fa[v][i-1];
            fa[v][i]=fa[k][i-1];
            sum[v][i]=sum[v][i-1]+sum[k][i-1];
            qsum[v][i]=qsum[v][i-1]+qsum[k][i-1];
        }
        for (k=fi[v];k;k=ne[k]){
            if (!cz[az[blg[la[k]]]]){
                dfs(az[blg[la[k]]],v);
            }
        }
    }
    void up(ll &a,ll i,ll &j,ll &k){
        j+=sum[a][i];
        k+=qsum[a][i];
        a=fa[a][i];
    }
    ll lca(ll a,ll b){
        ll i,j=0,k=0;
        if (de[a]<de[b]) swap(a,b);
        for (i=ln(de[a]-de[b],2);i>=0;i--) if (de[fa[a][i]]>de[b]) up(a,i,j,k);
        if (de[a]!=de[b]) up(a,0,j,k);
        for (i=ln(de[a],2);i>=0;i--) if (fa[a][i]!=fa[b][i]) up(a,i,j,k),up(b,i,j,k);
        if (a!=b) up(a,0,j,k),up(b,0,j,k);
        j+=sum[a][0];
        k+=qsum[a][0];
        return sqr(j)-k;
    }
    void tarjan(ll v,ll from){
        ll i,j,k;
        dfn[v]=low[v]=++num;
        bz[j=stack[++stack[0]]=v]=true;
        for (k=fi[v];k;k=ne[k])
            if (!dz[(k+1)/2]){
                dz[(k+1)/2]=true;
                if (!dfn[la[k]]){
                    tarjan(la[k],v);
                    low[v]=min(low[la[k]],low[v]);
                }else if (bz[la[k]]) low[v]=min(low[v],dfn[la[k]]);
            }
        if (low[v]==dfn[v]){
            while (stack[stack[0]]!=j){
                blg[stack[stack[0]]]=v;
                bz[stack[stack[0]--]]=false;
            }
            blg[stack[stack[0]]]=v;
            bz[stack[stack[0]--]]=false;
        }
    }
    int main(){
        cnt=n=read();m=read();t=read();
        for (i=1;i<=m;i++){
            j=read();k=read();
            add_line(j,k);
            add_line(k,j);
        }
        tarjan(1,0);
        for (i=1;i<=n;i++){
            if (!az[blg[i]]) az[blg[i]]=++cnt;
            sum[az[blg[i]]][0]++;
            for (k=fi[i];k;k=ne[k]) add_line(az[blg[i]],la[k]);
        }
        dfs(n+1,0);
        for (i=1;i<=t;i++){
            j=read();
            k=read();
            ans+=lca(az[blg[j]],az[blg[k]]);
        }
        printf("%lld
    ",ans);
        return 0;
    }

    启发

    边双连通分量在某种程度上等同于强连通分量。

  • 相关阅读:
    Python爬虫常用请求头User-Agent
    python使用清华镜像源安装工具包selenium,解决直接pip install安装慢的问题
    工于擅其事必先利其器-全家桶的激活
    user.vue
    Gateway流量的入口,API全托管,协议适配,防刷
    nacos配置服务2
    项目笔记
    sql性能优化
    windows脚本
    js时间格式化参考文档
  • 原文地址:https://www.cnblogs.com/hiweibolu/p/6714892.html
Copyright © 2011-2022 走看看