标签:
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