分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

POJ - 3417 Network (LCA+树上差分)

发布时间:2023-09-06 02:16责任编辑:郭大石关键词:暂无标签

题目传送门:POJ - 3417 Network

题目大意:

存在一棵n个结点的树,加入m条新边,现在要让这个图不连通,你可以切断两条边,要求切断一条原边,一条新边,求切割的方案数。

分析:

加入m条新边,假设加入新边(u,v),那么u-->lca(u,v)-->v-->u形成一个环,此时可以切断新边,和环上任意的一条原边就可以使图不连通。

可以发现若加入一条新边,给环上的计数1,表示该边被一个环覆盖,树上有些边会被多个环覆盖,此时可以分情况讨论。

1、若该边被覆盖次数是0,则断掉该边后图已经满足不连通条件了,此时可以断掉任意一条新边,图依旧不连通,可该边以产生m种新方案。

2、若该边被覆盖次数是1,则断掉该边后必须断掉与之对应的新边才能使图不连通,可以产生1种新方案。

3、若该边被覆盖次数大于等于2,则不能在断掉一条新边和一条原边的情况下使图不连通,所以不能产生新方案。

所以该题目可以转化为,每次加入新边后,给形成对应的环上的边+1,最后统计树上所有边的权值(树上差分),若权值是0方案数+m,权值是1方案数+1

可以求出最后结果

代码

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const int MAX=100009;const int M=20;int n,m,a,b;int head[MAX],cnt=0;int up[MAX][M];int deep[MAX];int de[MAX];struct edge{ ???int next,to;}edge[MAX*2];inline void add(int u,int v){ ???edge[cnt].to=v; ???edge[cnt].next=head[u]; ???head[u]=cnt++;} ???void dfs(int u) ???????????????????????????????????????????????????//遍历数,求出结点的深度和父亲 { ???????????????for(int i=head[u];i!=-1;i=edge[i].next) ???????????????????{ ???????int to=edge[i].to; ???????if(to==up[u][0])continue; ???????deep[to]=deep[u]+1; ???????up[to][0]=u; ???????dfs(to); ???}}void init(){ ???memset(up,-1,sizeof(up)); ???deep[1]=1; ???dfs(1); ???for(int j=1;(1<<j)<=n;j++) ???????????????????????????????????//倍增 ????????for(int i=1;i<=n;i++) ???????????if(~up[i][j-1]) ???????????????up[i][j]=up[up[i][j-1]][j-1];}int lca(int a,int b){ ???if(deep[a]<deep[b]) ???????swap(a,b); ???int d=deep[a]-deep[b]; ???for(int i=0;i<M;i++) ???????if(d&(1<<i)) ???????????a=up[a][i]; ???????if(a==b)return a; ???for(int i=M-1;i>=0;i--) ???{ ???????if(up[a][i]!=up[b][i]) ???????????a=up[a][i],b=up[b][i]; ???} ???return up[a][0];}void dfs_ans(int u) ????????????????????????????????????????????????{ ???for(int i=head[u];i!=-1;i=edge[i].next) ???{ ???????int to=edge[i].to; ???????if(to==up[u][0])break; ????????dfs_ans(to); ???????de[u]=de[u]+de[to]; ???????}}int main(){ ???memset(head,-1,sizeof(head)); ???memset(de,0,sizeof(de)); ???scanf("%d%d",&n,&m); ???for(int i=1;i<n;i++) ???{ ???????scanf("%d%d",&a,&b); ???????add(a,b); ???????add(b,a); ???} ???init(); ???for(int i=0;i<m;i++) ???{ ???????scanf("%d%d",&a,&b); ???????de[a]++; ???????????????????????????????//树上差分 ????????de[b]++; ???????de[lca(a,b)]-=2; ???} ???dfs_ans(1); ???int res=0; ???for(int i=2;i<=n;i++) ????????????????????????????{ ???????if(de[i]==0) ???????????res+=m; ???????if(de[i]==1) ???????????res++; ???} ???printf("%d\n",res); ???return 0;} 

POJ - 3417 Network (LCA+树上差分)

原文地址:https://www.cnblogs.com/LjwCarrot/p/9738045.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved