HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】ACdream 1429——Diversion——————【树链剖分】
Minimum Cut
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 895 Accepted Submission(s): 387
We say that a cut in G respects T if it cuts just one edges of T.
Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph G respecting the given spanning tree T.
The first line of the input is a single integer t (1≤t≤5) which is the number of test cases.
Then t test cases follow.
Each test case contains several lines.
The first line contains two integers n (2≤n≤20000) and m (n−1≤m≤200000).
The following n−1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge.
Next m−n+1 lines describe the undirected graph G and each of them contains two integers u and v corresponding to an edge which is not in the spanning tree T.
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
struct Edge{
int v,w,next;
}edges[maxn*5];
int head[maxn];
int fa[maxn],dep[maxn],siz[maxn],son[maxn];
int top[maxn],w[maxn];
int c[maxn];
int tot,totw;
const int INF=0x3f3f3f3f;
void init(){
tot=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
}
void addedge(int _u,int _v){
edges[tot].v=_v;
edges[tot].next=head[_u];
head[_u]=tot++;
edges[tot].v=_u;
edges[tot].next=head[_v];
head[_v]=tot++;
}
void dfs1(int u,int _fa,int _dep ){ //得到dep数组、fa数组、siz数组、son数组
dep[u] = _dep;
fa[u] = _fa;
siz[u] = 1;
for(int i=head[u]; i!=-1; i=edges[i].next){
Edge &e = edges[i];
if(e.v != _fa){
dfs1(e.v,u, _dep+1);
siz[u]+=siz[ e.v ];
if(son[u]==-1 || siz[son[u]] <siz[e.v]){
son[u] = e.v;
}
}
}
}
void dfs2(int u,int _top){ //得到top数组、w数组
top[u]=_top;
w[u]=totw++;
if(son[u]!=-1){
dfs2(son[u],_top);
for(int i=head[u]; i != -1; i = edges[i].next){
Edge &e = edges[i];
if(e.v != fa[u]&&e.v!=son[u]){
dfs2(e.v,e.v);
}
}
}
}
void update(int u,int v,int val){ //修改u---v路径上的权值
int f1=top[u],f2=top[v]; //找到u,v所在重链的链头
while(f1!=f2){ //处理不在同一条重链上的情况
if(dep[f1]<dep[f2]){
swap(f1,f2);
swap(u,v);
}
c[w[f1]] +=val; //这里用的是差分前缀和的方法实现
c[w[u]+1]-=val;
u=fa[f1];
f1=top[u];
}
if(dep[u]>dep[v]){ //让u处于靠近根的位置
swap(u,v);
}
c[w[son[u]]]+=val; //处理在同一条重链上的情况
c[w[v]+1]-=val;
}
int main(){
int t,n,m,cnt=0;
scanf("%d",&t);
while(t--){
init();
scanf("%d%d",&n,&m);
int a,b;
for(int i=1;i<=n-1;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
}
dfs1(1,-1,1);
totw=1;
dfs2(1,1);
memset(c,0,sizeof(c));
for(int i=1;i<=m-n+1;i++){
scanf("%d%d",&a,&b);
update(a,b,1);
}
for(int i=1;i<=n;i++){
c[i]+=c[i-1];
}
int ans=INF;
for(int i=1;i<=n;i++){
if(c[i]!=0&&c[i]){
ans=min(ans,c[i]);
}
}
printf("Case #%d: %d\n",++cnt,ans+1);
}
return 0;
}
Diversion
Problem Description
Let us denote the number of stone roads needed to get from city u to city v as s(u, v). The roads were created long ago and follow the strange rule: if two cities u and v are connected by a road (no matter,stone or country), then either s(1, u) + s(u, v) = s(1, v ) or s(1, v ) + s(v, u) = s(1, u).
The king of Edgeland is planning to attack Farland. He is planning to start his operation by destroying some roads. Calculations show that the resources he has are enough to destroy one stone road and one country road. The king would like to destroy such roads that after it there were at least two cities in Farland not connected by roads any more.
Now he asks his minister of defense to count the number of ways he can organize the diversion. But the minister can only attack or defend, he cannot count. Help him!
Input
Output
Output one integer number — the number of ways to organize the diversion.
Sample Input
6 7
1 2 1
2 3 1
1 4 0
3 4 1
4 5 1
3 6 0
5 6 1
Sample Output
4 解释:这个题目跟上面那个基本一样,只是最后让求的结果略有不同。这个题目问只同时删掉树上一条边,和新加的边能让图不连通的方式有多少种。那么只需要统计最后边权为1的边有多少条即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5;
struct Edge{
int v,w,next;
}edges[maxn*5];
struct Country{
int x,y;
}countrys[maxn];
int head[maxn];
int fa[maxn],dep[maxn],siz[maxn],son[maxn];
int top[maxn],w[maxn];
int c[maxn];
int tot,totw;
const int INF=0x3f3f3f3f;
void init(){
tot=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
}
void addedge(int _u,int _v){
edges[tot].v=_v;
edges[tot].next=head[_u];
head[_u]=tot++;
edges[tot].v=_u;
edges[tot].next=head[_v];
head[_v]=tot++;
}
void dfs1(int u,int _fa,int _dep ){ //得到dep数组、fa数组、siz数组、son数组
dep[u] = _dep;
fa[u] = _fa;
siz[u] = 1;
for(int i=head[u]; i!=-1; i=edges[i].next){
Edge &e = edges[i];
if(e.v != _fa){
dfs1(e.v,u, _dep+1);
siz[u]+=siz[ e.v ];
if(son[u]==-1 || siz[son[u]] <siz[e.v]){ //得到u的重儿子
son[u] = e.v;
}
}
}
}
//top[i]表示i节点所在重链的链头节点、w[i]表示i节点的父边在线段中的位置
void dfs2(int u,int _top){ //得到top数组、w数组
top[u]=_top;
w[u]=totw++;
if(son[u]!=-1){
dfs2(son[u],_top);
for(int i=head[u]; i != -1; i = edges[i].next){
Edge &e = edges[i];
if(e.v != fa[u]&&e.v!=son[u]){
dfs2(e.v,e.v);
}
}
}
}
void update(int u,int v,int val){ //修改u---v路径上的权值
int f1=top[u],f2=top[v]; //找到u,v所在重链的链头
while(f1!=f2){ //处理不在同一条重链上的情况
if(dep[f1]<dep[f2]){
swap(f1,f2);
swap(u,v);
}
c[w[f1]] +=val; //这里用的是差分前缀和的方法实现
c[w[u]+1]-=val;
u=fa[f1];
f1=top[u];
}
if(dep[u]>dep[v]){ //让u处于靠近根的位置
swap(u,v);
}
c[w[son[u]]]+=val; //处理在同一条重链上的情况
c[w[v]+1]-=val;
}
int main(){
int n,m,cnt=0,mm;
while( scanf("%d%d",&n,&m)!=EOF){
mm=0;
init();
int a,b,cc;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&cc);
if(cc==1)
addedge(a,b);
else countrys[++mm].x=a,countrys[mm].y=b;
}
dfs1(1,-1,1);
totw=1;
dfs2(1,1);
memset(c,0,sizeof(c));
for(int i=1;i<=mm;i++){
a=countrys[i].x;
b=countrys[i].y;
update(a,b,1);
}
for(int i=1;i<=n;i++){
c[i]+=c[i-1];
}
int ans=0;
for(int i=2;i<=n;i++){
if(c[i]==1){
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}
HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】ACdream 1429——Diversion——————【树链剖分】的更多相关文章
- Hdu 5452 Minimum Cut (2015 ACM/ICPC Asia Regional Shenyang Online) dfs + LCA
题目链接: Hdu 5452 Minimum Cut 题目描述: 有一棵生成树,有n个点,给出m-n+1条边,截断一条生成树上的边后,再截断至少多少条边才能使图不连通, 问截断总边数? 解题思路: 因 ...
- hdu 5452 Minimum Cut 树形dp
Minimum Cut Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=54 ...
- HDU 5452 Minimum Cut(LCA)
http://acm.hdu.edu.cn/showproblem.php?pid=5452 题意: 有一个连通的图G,先给出图中的一棵生成树,然后接着给出图中剩余的边,现在要删除最少的边使得G不连通 ...
- HDU 5452 Minimum Cut
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5452题目大意: 给你一个图G,图中包含一颗生成树.要求只能删除生成树内的一条边,使得图不联通.问最小的删除 ...
- HDU 5452 Minimum Cut (Spaning Tree)
生成树的上的一个非根结点对应一条生成树上的边,然后这个结点的子树上连出去的边就对应去掉这条边的割, 然后就可以对树外的边求LCA,在LCA上标记,利用这个信息可以算出有多少条边在子树上,以及有多少条边 ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 树链剖分+差分前缀和优化
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例: 输出样例: 说明 说明 思路 AC代码 优化 优化后AC代码 总结 题面 题目链接 P3258 [JLOI2 ...
- hdu 1394 Minimum Inversion Number(这道题改日我要用线段树再做一次哟~)
Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...
- ACdream 1424 Diversion( 树链剖分 )
Diversion Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) Submit St ...
- AcWing243一个简单的整数问题2(树状数组+差分+前缀和规律)
题目地址:https://www.acwing.com/problem/content/244/ 题目描述: 给定一个长度为N的数列A,以及M条指令,每条指令可能是以下两种之一: 1.“C l r d ...
随机推荐
- Go语言是如何处理栈的
转自:http://tonybai.com/2014/11/05/how-stacks-are-handled-in-go/ Go 1.4Beta1刚刚发布,在Go 1.4Beta1中,Go语言的st ...
- Python循环-break和continue
break用于完全结束一个循环,跳出循环体,执行循环后面的语句 # -*- coding:utf-8 -*- __author__ = "MuT6 Sch01aR" count = ...
- javascript基础之两种函数的定义方法
第一种方式:可以在函数定义之前调用也可以在函数定义之后调用: (0)函数的调用 add(,) //可以调用 (1)函数的定义: function add(x,y) { console.log(x+y) ...
- UpdatePanel无刷新
使用UpdatePanel实现无刷新效果 1. <asp:ScriptManager ID="scriptManger1" ruant="server"& ...
- 【java并发编程艺术学习】(四)第二章 java并发机制的底层实现原理 学习记录(二) synchronized
章节介绍 本章节主要学习 Java SE 1.6 中为了减少获得锁 和 释放锁 时带来的性能消耗 而引入的偏向锁 和 轻量级锁,以及锁的存储结构 和 升级过程. synchronized实现同步的基础 ...
- (转)Maven 项目新建index.jsp报错问题
原文:http://blog.csdn.net/dream_ll/article/details/52198656 最近用eclipse新建了一个maven项目,结果刚新建完成index.jsp页面就 ...
- 第二篇elasticsearch配置
1.去github搜索 elashsearch——head,以mobz开头的2.在根目录下安装npm install 3.修改elashsearch下的config文件下的elashsearch.yu ...
- (转自精通Python设计模式)Python设计模式之创建型模式——2.建造者模式
建造者模式将一个复杂对象的构造过程与其表现分离,这样,同一个构造过程可用于创建多个不同的表现. 我们来看个实际的例子,假设我们想要创建一个HMTL页面生成器,HTML页面的基本结构(构造组件)通常是一 ...
- 8、泛型程序设计与c++标准模板库2.3双端队列容器
双端队列容器是一种放松了访问权限的队列.除了从队列的首部和尾部访问元素外,标准的双端队列也支持通过使用下标操作符"[]"进行直接访问. 它提供了直接访问和顺序访问方法.其头文件为& ...
- Unity技术支持团队性能优化经验分享
https://mp.weixin.qq.com/s?__biz=MzU5MjQ1NTEwOA==&mid=2247490321&idx=1&sn=f9f34407ee5c5d ...