hdu4916 Count on the path

调了好久。。。。

•把树视为以1为根的有向树,然后将1删除
•原树变为一个森林,并且任一棵树的根节点均为原树中1的子节点
•只需要考虑最小编号前3小的三棵树
•记f[x][y]为去掉x和y两棵树后的最小值
•记dui[u]为u节点所在的树的根节点
•记dp[u]为在dui[u]这颗树中,不在路径<dui[u], u>上的节点编号最小值
•对于经过根节点的询问<u, v>
•ans<u, v> = min(dp[u], dp[v], f[bel[u]][bel[v]])
•维护g[x][0]和g[x][1],分别表示以x的子节点为根的子树中,编号最小值和次小值
•记F[x]为删除<bel[x], x>这条路径及x的子树,编号的最小值
•dp[u] = min(F[u], g[u][0])
•时间复杂度O(N),空间复杂度O(N)
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstdlib>
  4 #include<string>
  5 #include<cstring>
  6 #include<cmath>
  7 #include<algorithm>
  8 #define re(i,l,r) for(int i=(l);i<=(r);i++)
  9 #define rre(i,r,l) for(int i=(r);i>=(l);i--)
 10 using namespace std;
 11 const int xxx=1000010;
 12 int n,m,head[xxx],Next[xxx<<1],zhi[xxx<<1],fa[xxx],ed;
 13 int g[xxx][2],f[4][4],dui[xxx],F[xxx],dp[xxx],xiao[3];
 14 void add(int a,int b)
 15 {
 16     Next[++ed]=head[a],head[a]=ed,zhi[ed]=b;
 17     Next[++ed]=head[b],head[b]=ed,zhi[ed]=a;
 18 }
 19 const int L=1e7;
 20 char in[L],*In,*End;
 21 char getc(){
 22     if(In==End){
 23         End=in+fread(in,1,L,stdin);
 24         if(in==End) return 0;
 25         In=in;
 26     }
 27     return *In++;
 28 }
 29 int inin(int &x){
 30     static char c;
 31     for(;c=getc(),!isdigit(c) && c;);
 32     if(!c) return 0;
 33     for(x=0;isdigit(c);c=getc()) (x*=10)+=c-'0';
 34     return 1;
 35 }
 36 void dfs(int x)
 37 {
 38     g[x][0]=2147483647;g[x][1]=2147483647;
 39     for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x])
 40     {
 41         fa[zhi[i]]=x;
 42         dfs(zhi[i]);
 43         int temp=min(g[zhi[i]][0],zhi[i]);
 44         if(temp<=g[x][0])
 45             g[x][1]=g[x][0],
 46             g[x][0]=temp;
 47         else g[x][1]=min(g[x][1],temp);
 48 //        else g[x][1]=min(g[x][1],g[zhi[i]][0]);
 49     }
 50 }
 51 void dfsxxx(int x,int t)
 52 {
 53     dui[x]=t;
 54     for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x])
 55         dfsxxx(zhi[i],t);
 56 }
 57 void dfs2(int x)
 58 {
 59     if(x>1&&fa[x]!=1)
 60         if(g[fa[x]][0]==min(g[x][0],x))
 61             F[x]=min(F[fa[x]],g[fa[x]][1]);
 62         else F[x]=min(F[fa[x]],g[fa[x]][0]);else ;
 63     if(fa[x]==1)F[x]=2147483647;
 64     dp[x]=min(F[x],g[x][0]);
 65     for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x])
 66         dfs2(zhi[i]);
 67 }
 68 //void dfs3(int x)
 69 //{
 70 //    for(int i=head[x];i;i=Next[i])if(zhi[i]!=fa[x])
 71 //        dfs3(zhi[i]);
 72 //}
 73 int hhh(int x)
 74 {
 75     x=dui[x];
 76     if(min(x,g[x][0])==xiao[0])return 0;
 77     else if(min(x,g[x][0])==xiao[1])return 1;
 78     else if(min(x,g[x][0])==xiao[2])return 2;
 79     else return 3;
 80 }
 81 int pre=0;
 82 int main()
 83 {
 84     freopen("in.in","r",stdin);
 85     freopen("out.out","w",stdout);
 86     while(inin(n))
 87     {
 88         inin(m);
 89         pre=0;
 90         memset(head,0,sizeof(head));ed=0;
 91         re(i,2,n)
 92         {
 93             int a,b;
 94 //            scanf("%d%d",&a,&b);
 95             inin(a),inin(b);
 96             add(a,b);
 97         }
 98         dfs(1);
 99         xiao[0]=xiao[1]=xiao[2]=n+1;
100         for(int i=head[1];i;i=Next[i])
101         {
102             dfsxxx(zhi[i],zhi[i]);
103             int temp=min(g[zhi[i]][0],zhi[i]);
104             if(xiao[0]>temp)
105                 xiao[2]=xiao[1],
106                 xiao[1]=xiao[0],
107                 xiao[0]=temp;
108             else if(xiao[1]>temp)
109                 xiao[2]=xiao[1],
110                 xiao[1]=temp;
111             else if(xiao[2]>temp)
112                 xiao[2]=temp;
113         }
114         f[3][3]=xiao[0];
115         f[3][0]=f[0][3]=xiao[1],f[3][1]=f[1][3]=xiao[0],f[3][2]=f[2][3]=xiao[0];
116         f[0][1]=f[1][0]=xiao[2],f[1][2]=f[2][1]=xiao[0],f[0][2]=f[2][0]=xiao[1];
117         dfs2(1);
118 //        dfs3(1);
119         dui[1]=-1;
120         re(i,1,m)
121         {
122             int a,b;
123 //            scanf("%d%d",&a,&b);
124             inin(a),inin(b);
125             a=a^pre,b=b^pre;
126             if(a==0)a++;if(b==0)b++;if(a>n)a=a%n+1;if(b>n)b=b%n+1;
127 //            printf("%d %d %d
",a,b,pre);
128             if(dui[a]==dui[b]&&dui[a]!=-1){pre=1;}
129             else if(a==1)
130                     if(b==1){pre=xiao[0];}
131                     else 
132                     {
133                         int now=hhh(b);
134                         re(i,0,2)if(i!=now){pre=min(dp[b],xiao[i]);break;} 
135                     }
136                 else if(b==1)
137                 {
138                     int now=hhh(a);
139                     re(i,0,2)if(i!=now){pre=min(dp[a],xiao[i]);break;}
140                 }
141                 else {pre=min(min(dp[a],dp[b]),f[hhh(a)][hhh(b)]);}
142             printf("%d
",pre);
143         }
144     }
145     return 0;
146 }
原文地址:https://www.cnblogs.com/HugeGun/p/5345642.html