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

    思路

    圆方树,一个点双中的所有点都可以被经过,所以给圆点赋值-1,方点赋值为圆点个数,统计圆点两两之间的路径权值和即可

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <stack>
    using namespace std;
    int v2[100100*4],fir2[100100*2],nxt2[100100*4],cnt2;
    void addedge2(int ui,int vi){
        ++cnt2;
        v2[cnt2]=vi;
        nxt2[cnt2]=fir2[ui];
        fir2[ui]=cnt2;
    }
    int v[100100*4],fir[100100*2],nxt[100100*4],cnt;
    void addedge(int ui,int vi){
        ++cnt;
        v[cnt]=vi;
        nxt[cnt]=fir[ui];
        fir[ui]=cnt;
    }
    int fd_cnt,dfn[100100*2],low[100100*2],w_p[100100*2],dfs_clock;
    int S[100100*2],topx=0,n,m,num;
    void dfs(int u){
        low[u]=dfn[u]=++dfs_clock;
        S[++topx]=u;
        num++;
        for(int i=fir[u];i;i=nxt[i]){
            if(!dfn[v[i]]){
                dfs(v[i]);
                low[u]=min(low[u],low[v[i]]);
                if(low[v[i]]==dfn[u]){
                    ++fd_cnt;
                    w_p[fd_cnt]=0;
                    for(int x=0;x!=v[i];topx--){
                        x=S[topx];
                        addedge2(fd_cnt,x);
                        addedge2(x,fd_cnt);
                        ++w_p[fd_cnt];
                    }
                    addedge2(u,fd_cnt);
                    addedge2(fd_cnt,u);
                    ++w_p[fd_cnt];    
                }
            }
            else
                low[u]=min(low[u],dfn[v[i]]);
        }
    }
    int sz[100100*2];
    long long ans;
    void dfs(int u,int f){
        sz[u]=(u<=n);
        for(int i=fir2[u];i;i=nxt2[i]){
            if(v2[i]==f)
                continue;
            dfs(v2[i],u);
            ans+=2LL*w_p[u]*sz[u]*sz[v2[i]];
            sz[u]+=sz[v2[i]];
        }
        ans+=2LL*w_p[u]*sz[u]*(num-sz[u]);    
    }
    int main(){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
            w_p[i]=-1;
        for(int i=1;i<=m;i++){
            int a,b;
            scanf("%d %d",&a,&b);
            addedge(a,b);
            addedge(b,a);
        }
        fd_cnt=n;
        for(int i=1;i<=n;i++)
            if(!dfn[i]){
                num=0;
                dfs(i);
                topx--;
                dfs(i,0);
            }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Linux命令之cat
    Linux命令之diff
    Linux查看内核信息或系统信息
    Linux命令之touch
    linux脚本:shell, 判断输入参数的个数(命令行)
    c++中try catch的用法
    linux命令:ftp
    linux shell种类
    linux shell脚本:在脚本中实现读取键盘输入,根据输入判断下一步的分支
    c语言,gdb
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10766117.html
Copyright © 2011-2022 走看看