2018.12.28-dtoj-3648-寝室管理
Posted jessie-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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<cstdio> #include<cstring> #include<iostream> using namespace std; typedef long long ll; const int N=1e5+5,M=2e5+5; int k,m,w,r,c,n,t[M],l[M],h[N],f[N],p[N],s[N],d[N]; bool b[N];ll a[N],q; int get(int x){return !f[x]?x:f[x]=get(f[x]);} void insert(int x,int y){ t[++c]=y,l[c]=h[x],h[x]=c; t[++c]=x,l[c]=h[y],h[y]=c; } void add(int x,int y=1){ for(;x<=n;x+=x&-x) if(p[x]!=c) p[x]=c,a[x]=y; else a[x]+=y; } ll sum(int x){ if(x<0) return 0; ll y=0; for(;x;x-=x&-x) if(p[x]==c) y+=a[x]; return y; } #define z t[i] void root(int x,int y){ int c=0;s[x]=1; for(int i=h[x];i;i=l[i]){ if(b[z] || y==z) continue; root(z,x); s[x]+=s[z]; c=max(c,s[z]); } c=max(c,m-s[x]); if(c<w) w=c,r=x; } void dfs1(int x,int y,int w){ s[x]=1;q+=sum(n)-sum(k-w-1); for(int i=h[x];i;i=l[i]){ if(b[z] || y==z) continue; dfs1(z,x,w+1);s[x]+=s[z]; } } void dfs2(int x,int y,int w){ add(w+1); for(int i=h[x];i;i=l[i]) if(!b[z] && y!=z) dfs2(z,x,w+1); } void solve(int x){ ++c;b[x]=1;add(1); for(int i=h[x];i;i=l[i]) if(!b[z]) dfs1(z,x,1),dfs2(z,x,1); for(int i=h[x];i;i=l[i]){ if(b[z]) continue; w=1e9;m=s[z]; root(z,x);solve(r); } } void dfs3(int x){ add(d[x]); for(int i=h[x];i;i=l[i]){ if(z==f[x]) continue; f[z]=x;d[z]=d[x]+1; dfs3(z); } } void dfs4(int x,int y){ add(d[x],-1); for(int i=h[x];i;i=l[i]) if(z!=y && !b[z]) dfs4(z,x); } void dfs5(int x,int y,int w){ q+=sum(n)-sum(k-w-1); for(int i=h[x];i;i=l[i]) if(z!=y && !b[z]) dfs5(z,x,w+1); } int main(){ int x,y,u,v,g=0,h; scanf("%d%d%d",&n,&m,&k); while(m--){ scanf("%d%d",&x,&y); u=get(x),v=get(y); if(u==v) g=x,h=y; else f[u]=v,insert(x,y); } c=0;m=n,w=1e9; root(1,0); solve(r); if(!g) return !printf("%lld ",q); memset(b,0,n+1); ++c;f[g]=0;d[g]=1;dfs3(g); for(int i=h;i;i=f[i]) b[i]=1; for(int i=h,j=1;i!=g;i=f[i],++j) dfs4(i,0),dfs5(i,0,j); printf("%lld ",q); return 0; }
以上是关于2018.12.28-dtoj-3648-寝室管理的主要内容,如果未能解决你的问题,请参考以下文章