标签:
Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
Total Submission(s): 895 Accepted Submission(s): 387
#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;
}
HDU 5452——Minimum Cut——————【树链剖分+差分前缀和】
标签:
原文地址:http://www.cnblogs.com/chengsheng/p/4836016.html