题干:

Given a simple unweighted graph GG (an undirected graph containing no loops nor multiple edges) with nn nodes and mm edges. Let TT be a spanning tree of GG. 
We say that a cut in GG respects TT if it cuts just one edges of TT.

Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph GG respecting the given spanning tree TT.

Input

The input contains several test cases. 
The first line of the input is a single integer t (1≤t≤5)t (1≤t≤5) which is the number of test cases. 
Then tt test cases follow.

Each test case contains several lines. 
The first line contains two integers n (2≤n≤20000)n (2≤n≤20000) and m (n−1≤m≤200000)m (n−1≤m≤200000). 
The following n−1n−1 lines describe the spanning tree TT and each of them contains two integers uu and vv corresponding to an edge. 
Next m−n+1m−n+1 lines describe the undirected graph GG and each of them contains two integers uu and vv corresponding to an edge which is not in the spanning tree TT.

Output

For each test case, you should output the minimum cut of graph GG respecting the given spanning tree TT.

Sample Input

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

Sample Output

Case #1: 2

题目大意:

给你一个图G,n个点m条边,图中给定一颗生成树(前n-1条输入的边)。问一个最小割的边数量(将图变成一个不连通图),要求需要包含给定生成树内的一条边。

解题报告:

因为有一条生成树内的边必选,所以这是个切入点,我们枚举生成树上的每一条边<U,V>,假设我们要删的边是<U,V>, 那么自然图就分成了两块,这也正是我们要的结果。我们所要做的就是让V的子树上的任何节点,不再和其V子树外的其他节点相连。使得他们完全分离开。

有了这个思路之后,就需要换一个角色重新考虑问题了,站在新加入的边的角度上看:对于每一条新加入的一条树T外的边<a,b>,  那么我们需要判断枚举到哪一条T内的边的时候,需要将这条边删除掉,不难观察出来,是ab两点相连的这条链上的边,那么树上维护这条链上的边计数+1,就转化成有根树然后树上差分即可。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e4 + 5;
int n,m,val[MAX];
struct Edge {int u,v;int ne;
} e[MAX*20];
int tot;
int head[MAX],f[MAX];
int fa[MAX][33],dep[MAX];
void add(int u,int v) {e[++tot].u = u;e[tot].v = v;e[tot].ne = head[u];head[u] = tot;
}
void dfs(int cur,int rt) {fa[cur][0] = rt;dep[cur] = dep[rt] + 1;for(int i = head[cur]; ~i; i = e[i].ne) {int v = e[i].v;if(v == rt) continue;dfs(v,cur);}for(int i = 1; i<=31; i++) {fa[cur][i] = fa[fa[cur][i-1]][i-1];}
}
int lca(int u,int v) {if(dep[u] < dep[v]) swap(u,v);int dc = dep[u] - dep[v];for(int i = 0; i<=31; i++) {if((1<<i) & dc) u = fa[u][i];}if(u == v) return u;for(int i = 31; i>=0; i--) {if(fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];}return fa[u][0];
}
int ans = 0x3f3f3f3f;
void DFS(int cur,int rt) {for(int i = head[cur]; ~i; i = e[i].ne) {if(e[i].v == rt) continue;DFS(e[i].v,cur);val[cur] += val[e[i].v];}if(cur != 1) ans = min(ans,val[cur]);
}
int main()
{int t,iCase=0;cin>>t;while(t--) {scanf("%d%d",&n,&m);tot=0,ans=0x3f3f3f3f;for(int i = 1; i<=n; i++) head[i] = -1,val[i]=0;for(int u,v,i = 1; i<=n-1; i++) {scanf("%d%d",&u,&v);add(u,v);add(v,u);}dfs(1,0);for(int u,v,i = n; i<=m; i++) {scanf("%d%d",&u,&v);val[u]++,val[v]++;val[lca(u,v)]-=2;}DFS(1,0);printf("Case #%d: %d\n",++iCase,ans+1);}return 0 ;
}

另一个解题报告:https://blog.csdn.net/cqbztsy/article/details/50706555

树形dp做法:https://www.cnblogs.com/qscqesze/p/4822468.html

对于这个点,如果要消除他和他父亲之间的联系的话,代价就是他的子树所有连向外界的边就好了

跑一遍dfs维护一下就行了。

(但是好像证明是不对的

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

这组数据,应该是1 1,但是下面这个代码输出的是1 2)

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 20050
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
//const int inf=0x7fffffff;   //нчоч╢С
const int inf=0x3f3f3f3f;
//*********************************************************************************vector<int> Q[maxn];
vector<int> E[maxn];
int vis[maxn];
int dp[maxn];
int ans;
void dfs(int x)
{vis[x]=1;for(int i=0;i<Q[x].size();i++){int y=Q[x][i];dfs(Q[x][i]);dp[x]+=dp[y]-1;}ans = min(ans,dp[x]);for(int i=0;i<E[x].size();i++)if(vis[E[x][i]])dp[E[x][i]]--;vis[x]=0;
}
int main()
{int t;scanf("%d",&t);for(int cas = 1;cas<=t;cas++){ans = 99999999;int n,m;scanf("%d%d",&n,&m);for(int i=0;i<=n;i++)Q[i].clear(),E[i].clear();memset(dp,0,sizeof(dp));memset(vis,0,sizeof(vis));for(int i=0;i<n-1;i++){int x,y;scanf("%d%d",&x,&y);dp[x]++,dp[y]++;if(x>y)swap(x,y);Q[x].push_back(y);}for(int i=n-1;i<m;i++){int x,y;scanf("%d%d",&x,&y);dp[x]++,dp[y]++;if(x>y)swap(x,y);E[y].push_back(x);}dfs(1);printf("Case #%d: %d\n",cas,ans);}
}

【HDU - 5452】Minimum Cut(树形dp 或 最近公共祖先lca+树上差分,转化tricks,思维)相关推荐

  1. HDU - 5452 Minimum Cut(LCA+树上差分)

    题目链接:点击查看 题目大意:给出n个点,n-1条边组成一棵树,然后再给出m-n-1条边,组成一个图,现在要让我们求最少删去几条边才能让整个图不连通,并且要求只能在树上删去最多一条边 题目分析:这个题 ...

  2. HDU - 5452 Minimum Cut LCA + imos和

    传送门:HDU5452 题意:给出一个无向图G,求图G的最小边割集,并且使得割边中有且仅有一条属于图G的生成树T. 思路:考虑生成树中的每一条边i,将其去掉后生成树就被划分成两部分,则全图的割边就是那 ...

  3. HDU - 1520 Anniversary party [树形dp]

    Anniversary party 时限:1000ms Problem Description There is going to be a party to celebrate the 80-th ...

  4. POJ 2342 | HDU 1520 Anniversary party 树形DP(入门题)

    传送门:POJ 2342 题目大意: 有若干人参加一个聚会,如果两个人之间有直接的上下属关系,则只能去一个.每个人都有个高兴值,问高兴值之和最大是多少? 思路: 之前一直觉得树形DP比较难,现在发现树 ...

  5. HDU 3534 Tree (经典树形dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3534 题意: 给你一棵树,问你有多少对点的距离等于树的直径. 思路: dp[i][0]表示在i的子树中 ...

  6. HDU 1011(星河战队 树形DP)

    题意是说在一个洞穴中有许多房间,每个房间中有一些虫子和大脑,这些房间之间用隧道相连形成一棵树,士兵们杀虫子的能力有限,也可以直接杀死虫子而不消耗士兵战斗力,但这样就无法得到房间中的大脑,士兵们不能走回 ...

  7. hdu 4044 GeoDefense (树形dp | 多叉树转二叉树)

    题目链接:hdu-4044 题意 这是一个塔防游戏,地图是一个n个编号为1-n的节点的树, 节点1是敌人的基地,其他叶子节点都是你的基地.    敌人的基地会源源不断地出来怪兽,为了防止敌人攻进你的基 ...

  8. HDU.5909.Tree Cutting(树形DP FWT/点分治)

    题目链接 \(Description\) 给定一棵树,每个点有权值,在\([0,m-1]\)之间.求异或和为\(0,1,...,m-1\)的非空连通块各有多少个. \(n\leq 1000,m\leq ...

  9. Hdu 5454,Minimum Cut,最近公共祖先+dfs遍历

    这道题补充了自己最近公共祖先的知识点: LCA(Lowest Common Ancestors)两种求法:①离线:tarjan+dfs:②在线算法,还没看 题意: 先给定一棵n个节点的树,然后给定一个 ...

最新文章

  1. $portfolio.isotope is not a function
  2. 防止非法链接(referer)
  3. Activity与Fragment的生命周期详解
  4. Kanzi常用操作2
  5. Ubuntu 使用记录
  6. 2014年3月29日缅甸将举行人口普查
  7. 6.组函数(avg(),sum(),max(),min(),count())、多行函数,分组数据(group by,求各部门的平均工资),分组过滤(having和where),sql优化...
  8. C语言中%c与%s的区别与划分
  9. Unity HTC Vive手柄汉诺塔操作
  10. 读取SPRING XML配置文件中的hbm.xml 文件列表.
  11. 牛客网产品笔试题刷题打卡——用户研究/项目管理
  12. php 阿里云短信接口 demo最新
  13. mysql 重做日志_mysql redo log 重做日志
  14. web前端面试题完美整理/涵盖html,CSS、JS、浏览器、Vue、React、移动web。
  15. android实现新闻内容显示功能,Android 类似新闻界面评论框
  16. java 删除重复文件
  17. MIMIC-IV- v2.0带着随访数据来啦
  18. 机器视觉领域专业词汇中英对照
  19. Java修炼之凡界篇 筑基期 第02卷 语法 第03话 数据类型
  20. 人工智能浪潮下,岗位及就业,技术分析 _证券交易员

热门文章

  1. 第一步:Axure 使用svn多人协作产品开发(提交文件)
  2. Palindrome subsequence HDU - 4632 区间dp|记忆化搜索
  3. 易语言执行linux脚本,初识易语言到编写SHELL生成器
  4. 软件质量保证计划_CMMI V2.0 精讲之“过程质量保证”
  5. 六自由度机器人逆向运动学_【课程笔记】Notes for Robotics/机器人学 (Part1)
  6. 整样运用计算机考试,2017年9月计算机二级考试《MS Office高级应用》上机操作题(2)...
  7. 小说中人称转换作用_长篇儿童小说《合欢》:一树红绒落马缨
  8. java一般做什么_java开发一般做什么
  9. shell判断false_Linux脚本shell常用判断式
  10. python3.6sysos_求大佬,这是什么情况啊