HDU 4297-One and One Story解题报告
2012-09-21 18:35
483 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=4297
这道题所给的图是一个森林,每一个子图都必有一个环(因为总边数为n),可以把环当做这棵树的根节点,那么如果两个点不在一棵树上,一定互相不可达,如果在一棵树上,如果两个点在同一棵子树上,那么一起到的点就是LCA,所以要维护森林的LCA,如果不在同一棵子树上,则要到各自的根节点,然后沿着环方向分别判断哪种情况是最优解。
View Code
这道题所给的图是一个森林,每一个子图都必有一个环(因为总边数为n),可以把环当做这棵树的根节点,那么如果两个点不在一棵树上,一定互相不可达,如果在一棵树上,如果两个点在同一棵子树上,那么一起到的点就是LCA,所以要维护森林的LCA,如果不在同一棵子树上,则要到各自的根节点,然后沿着环方向分别判断哪种情况是最优解。
View Code
#pragma comment(linker, "/STACK:10240000000,10240000000") #include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define N 500005 #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) using namespace std; int nxt ; int root ;//点是否在环上,在环上是环上的第几个点 int father ;//在环上的父节点 int num ;//所在环的节点个数 int f ;//并查集判断是否是在一个树上,并且可以确定环 int list[2*N]; int fir[2*N],ti;//rmq解决LCA问题 bool used ; int deep[2*N]; int n; int head ,cnt; struct node { int v,next; }; node edge ;//要加反向边 void add(int u,int v) { edge[cnt].v=v,edge[cnt].next=head[u],head[u]=cnt++; } int find(int x) { int r=x; while(r!=f[r]) r=f[r]; int t1; while(x!=f[x]) { t1=f[x]; f[x]=r; x=t1; } return r; } void uni(int x,int y) { int t1=find(x); int t2=find(y); if(t1==t2)//发现一个点和其所要连接的点在一个集合时,说明产生了环 { int cnt1=0; int temp=x; do { root[x]=++cnt1; x=nxt[x]; }while(!root[x]); x=temp; num[x]=cnt1; x=nxt[x]; while(x!=temp) { num[x]=cnt1; x=nxt[x]; } } else f[t1]=t2; } int dp[2*N][22]; void makermq() { int i,j; for(i=1;i<ti;i++) dp[i][0]=deep[i]; for(j=1;(1<<j)<ti;j++) { for(i=1;i+(1<<j)-1<ti;i++) dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } } int rmq(int s,int e) { int k=(int)(log((e-s+1)*1.0)/log(2.0)); return min(dp[s][k],dp[e-(1<<k)+1][k]); } void init() { memset(dp,0x3f,sizeof(dp)); memset(root,0,sizeof(root)); memset(num,0,sizeof(num)); memset(head,-1,sizeof(head)); memset(used,0,sizeof(used)); memset(deep,0,sizeof(deep)); memset(fir,0,sizeof(fir)); memset(father,0,sizeof(father)); memset(list,0,sizeof(list)); cnt=0; ti=1; int i; for(i=1;i<=n;i++) { f[i]=i; } } void dfs(int u,int d,int v) { used[u]=true; if(root[u]) { d=1; v=u; } list[ti]=u; deep[ti]=d; fir[u]=ti; ti++; father[u]=v; int i; for(i=head[u];i>=0;i=edge[i].next) { if(!used[edge[i].v]) { dfs(edge[i].v,d+1,v); list[ti]=u; deep[ti]=d; ti++; } } } int main() { int i,j,m,a,b,temp,t1,t2; while(scanf("%d%d",&n,&m)!=EOF) { init(); for(i=1;i<=n;i++) { scanf("%d",&nxt[i]); add(nxt[i],i); uni(i,nxt[i]); } for(i=1;i<=n;i++) if(root[i]&&(!used[i])) dfs(i,1,i); makermq(); for(i=1;i<=m;i++) { scanf("%d%d",&a,&b); if(find(a)!=find(b)) { printf("-1 -1\n"); continue; } if(father[a]==father[b]) { t1=a,t2=b; if(fir[a]>fir[b])//这里要特别注意 { t1=b,t2=a; } temp=rmq(fir[t1],fir[t2]); printf("%d %d\n",deep[fir[a]]-temp,deep[fir[b]]-temp); } else { temp=num[father[a]]; t1=deep[fir[a]]-1; t2=deep[fir[b]]-1; int fa=father[a]; int fb=father[b]; int ans1=t1,ans2=t2; if(root[fa]<root[fb]) { ans1+=(root[fb]-root[fa]); ans2+=(root[fa]+num[fa]-root[fb]); } else { ans1+=(root[fb]+num[fb]-root[fa]); ans2+=(root[fa]-root[fb]); } if(max(ans1,t2)<max(t1,ans2)) { printf("%d %d\n",ans1,t2); } else if(max(ans1,t2)>max(t1,ans2)) { printf("%d %d\n",t1,ans2); } else { if(min(ans1,t2)<min(t1,ans2)) { printf("%d %d\n",ans1,t2); } else if(min(ans1,t2)>min(t1,ans2)) { printf("%d %d\n",t1,ans2); } else { if(ans1>=t2) { printf("%d %d\n",ans1,t2); } else { printf("%d %d\n",t1,ans2); } } } } } } return 0; }
相关文章推荐
- hdu 4297 One and One Story
- LCA HDU 4297 One and One Story
- HDU 4297 One and One Story (LCA->RMQ)
- HDU 4297 One and One Story [有向带环图LCA]
- 解题报告:HDU_3988 Harry Potter and the Hide Story 大素数分解+勒让德
- hdu 4297 One and One Story
- hdu 4297 One and One Story(维护森林中的LCA)
- hdu 4297 One and One Story
- HDU 4297 One and One Story 分类讨论, LCA 2012年成都网络赛J题
- hdu 4297 One and One Story (维护森林中的LCA)
- HDU 4297 One and One Story(图-最近公共祖先)
- HDU 4297 One and One Story 树lca转rmq 并查集维护根节点环
- hdu 4283 You Are the One 区间DP 解题报告
- 【原】 POJ 3517 And Then There Was One Joseph问题 解题报告
- HDU-1078___FatMouse and Cheese —— 解题报告 dp动态数组
- BestCoder7 1001 Little Pony and Permutation(hdu 4985) 解题报告
- HDU:1222wolf and habbit解题报告
- hdu 1312 Red and Black 解题报告
- HDU - 1028 Ignatius and the Princess III解题报告(线性dp)
- 【HDOJ】4297 One and One Story