zoukankan      html  css  js  c++  java
  • 2018.12.28-dtoj-3648-寝室管理

    题目描述:

    T64有一个好朋友,叫T128。T128是寄宿生,并且最近被老师叫过去当宿管了。宿管可不是一件很好做的工作,碰
    巧T128有一个工作上的问题想请T64帮忙解决。T128的寝室条件不是很好,所以没有很多钱来装修。礼间寝室仅由n
    -1条双向道路连接,而且任意两间寝室之间都可以互达。最近,T128被要求对一条路径上的所有寝室进行管理,这
    条路径不会重复经过某个点或某条边。但他不记得是哪条路径了。他只记得这条路径上有不少于k个寝室。于是,
    他想请T64帮忙数一下,有多少条这样的路径满足条件。嗯…还有一个问题。由于最近有一些熊孩子不准晚上讲话
    很不爽,他们决定修筑一条“情报通道”,如果通道建成,寝室就变成了一个N个点N条边的无向图。并且,经过“
    情报通道”的路径也是合法的。T128心想:通道建成之前,T64还有一个高效的算法帮我数路径条数,但是通道建
    成之后,他还有办法吗?对,T64手忙脚乱,根本数不清有多少条路径。于是他找到了你

    算法标签:点分治

    思路:

    当m==n-1时是裸的点分治,考虑再加一条边,统计对答案的贡献,对于加边后构成的环,依此枚举断掉每一条边的贡献,怎么断不会算重的问题看代码吧。

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define LL long long
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e5+5;struct node{int l,r;}P;bool vis[N],tag[N];LL ans;
    int n,m,head[N],ne[N<<1],to[N<<1],cnt,fa[N],son[N],sz[N],size,A[N],f[N],tot,B[N],nt,rt,k,bef[N],dis[N],way[N];
    il int read(){int x;char ch;_(!);x=ch^48;_()x=(x<<1)+(x<<3)+(ch^48);return x;}
    il void insert(int x,int y){ne[++cnt]=head[x];head[x]=cnt;to[cnt]=y;}
    il int getfa(int x){if(!fa[x])return x;return fa[x]=getfa(fa[x]);}
    il int query(int x){int res=0;for(;x;x-=x&-x)res+=f[x];return res;}
    il void ins(int x,int v){for(;x<=n;x+=x&-x)f[x]+=v;}
    il void getrt(int x,int fa){
        son[x]=0;sz[x]=1;
        for(int i=head[x];i;i=ne[i]){
            if(fa==to[i]||vis[to[i]])continue;
            getrt(to[i],x);sz[x]+=sz[to[i]];
            if(sz[to[i]]>son[x])son[x]=sz[to[i]];
        }
        son[x]=max(son[x],size-sz[x]);if(son[x]<son[rt])rt=x;
    }
    il void getval(int x,int fa,int dep){
        A[++tot]=dep+1;ans+=query(n)-query(max(k-dep-1,0));
        for(int i=head[x];i;i=ne[i])if(fa!=to[i]&&!vis[to[i]])getval(to[i],x,dep+1);
    }
    il void solve(int x){
        vis[x]=1;B[nt=1]=1;ins(1,1);
        for(int i=head[x];i;i=ne[i]){
            if(vis[to[i]])continue;
            tot=0;getval(to[i],x,1);
            for(int i=1;i<=tot;i++)ins(A[i],1),B[++nt]=A[i];
        }
        for(int i=1;i<=nt;i++)ins(B[i],-1);
        for(int i=head[x];i;i=ne[i]){
            if(vis[to[i]])continue;
            rt=0;size=sz[to[i]];getrt(to[i],x);
            solve(rt);
        }
    }
    il void dfs1(int x,int fa,int dep){
        bef[x]=fa;ins(dis[x]=dep,1);
        for(int i=head[x];i;i=ne[i])if(fa!=to[i])dfs1(to[i],x,dep+1);
    }
    il void del(int x,int fa){
        ins(dis[x],-1);
        for(int i=head[x];i;i=ne[i])if(!tag[to[i]]&&fa!=to[i])del(to[i],x);
    }
    il void cal(int x,int fa,int dep){
        ans+=query(n)-query(max(0,k-dep-1));
        for(int i=head[x];i;i=ne[i])if(!tag[to[i]]&&fa!=to[i])cal(to[i],x,dep+1);
    }
    int main()
    {
        n=read();m=read();k=read();
        if(m==n-1){
            for(int i=1;i<n;i++){int x=read(),y=read();insert(x,y);insert(y,x);}
        }
        else{
            for(int i=1;i<=n;i++){
                int l=read(),r=read();
                int x=getfa(l),y=getfa(r);
                if(x==y)P=(node){l,r};
                else fa[x]=y,insert(l,r),insert(r,l);
            }
        }
        son[0]=n;rt=0;size=n;getrt(1,0);solve(rt);
        if(m==n){
            dfs1(P.l,0,1);tot=0;
            for(int i=P.r;i;i=bef[i])tag[way[++tot]=i]=1;
            for(int i=1;i<tot;i++)del(way[i],0),cal(way[i],0,i);
        }
        printf("%lld
    ",ans);
        return 0;
    }
    View Code
     
  • 相关阅读:
    四、oracle 用户管理二
    三、oracle 用户管理一
    二、oracle sql*plus常用命令
    数据库的导入导出
    一:oracle系统包—-dbms_output用法
    数据库分类
    Oracle序列号详解
    Windows 下 java(JDK)的安装和环境变量的配置
    win7安装oracle 10g时发生“程序异常终止。发生内部错误”的提示
    对数据库列的操作
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10193461.html
Copyright © 2011-2022 走看看