http://acm.hdu.edu.cn/showproblem.php?pid=5452
1 4 5 1 2 2 3 3 4 1 3 1 4
Case #1: 2
/* hdu5452 || 沈阳网络赛1003题 最近公共祖先问题 题目大意:给定一个图的一棵生成树然后给出一些其他的边,没有重边和自环,问在取且仅取一条树边的前提下,图的最小割边的数量是多少 解题思路:num维护每个子树与外界的相连边的数量,对于每个非树枝边,每加一条其最近公共祖先的num值就要-2,最后用栈统计一下就可以了 */ #include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <stack> using namespace std; const int inf=0x3f3f3f3f; const int maxn=111111; const int maxm=411111; int n,m,num[maxn],du[maxn],fa[maxn]; struct note { int v; int w; int next; }; struct SGRAPH { int head[maxn],ip; note edge[maxm]; void init() { memset(head,-1,sizeof(head)); ip=0; } void addedge(int u,int v,int c) { edge[ip].v=v,edge[ip].w=c,edge[ip].next=head[u],head[u]=ip++; } int d[maxn][20]; void makeRmqIndex(int A[],int n){ for(int i=1;i<=n;i++) d[i][0]=i; for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;i++) d[i][j] = A[d[i][j-1]] < A[d[i+(1<<(j-1))][j-1]]? d[i][j-1]:d[i+(1<<(j-1))][j-1]; } int rmqIndex(int L,int R,int A[]) { int k=0; while ((1<<(k+1))<=R-L+1) k++; return A[d[L][k]]<A[d[R-(1<<k)+1][k]]? d[L][k]:d[R-(1<<k)+1][k]; } //--------------------- int E[maxn*2],R[maxn],D[maxn*2],mn; void dfs(int u,int p,int d){ E[++mn]=u; D[mn]=d; R[u]=mn; fa[u]=p; for (int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if (v==p) continue; du[u]++; dfs(v,u,d+1); E[++mn]=u; D[mn]=d; } } void LCA_init(){ mn=0; memset(R,0,sizeof(R)); dfs(1,-1,1); makeRmqIndex(D,mn); //getd(1,-1,0); } int LCA(int u,int v){ if (R[u]>=R[v]) return E[rmqIndex(R[v],R[u],D)]; else return E[rmqIndex(R[u],R[v],D)]; } } solver; int main() { int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); solver.init(); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); solver.addedge(u,v,1); solver.addedge(v,u,1); } memset(du,0,sizeof(du)); solver.LCA_init(); memset(num,0,sizeof(num)); for(int i=n;i<=m;i++) { int u,v; scanf("%d%d",&u,&v); num[u]++; num[v]++; int ans=solver.LCA(u,v); num[ans]-=2; } stack<int>st; for(int i=1;i<=n;i++) { if(du[i]==0)st.push(i); } while(!st.empty()) { int v=st.top(); st.pop(); int u=fa[v]; du[u]--; num[u]+=num[v]; if(du[u]==0&&u>0) st.push(u); } int ans=inf; for(int i=2;i<=n;i++) { //printf("%d::%d\n",i,num[i]); ans=min(ans,num[i]); } printf("Case #%d: %d\n",++tt,ans+1); } return 0; }