数学

多项式

拉格朗日插值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

#define int long long
using namespace std;

const int maxn=5050;
const int modp=998244353;

int h[maxn],y[maxn];
int n,m,ans;

inline int ksm(int x,int y)
{
int ans=1;
while(y)
{
if(y&1) ans=(ans*x)%modp;
x=(x*x)%modp;
y>>=1;
}
return ans;
}

int getg(int i)
{
int ans=y[i];
int s1=1,s2=1;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
s1=s1*(m-h[j])%modp;
s2=s2*(h[i]-h[j])%modp;
}
ans=ans*(s1*ksm(s2,modp-2)%modp)%modp;
return ans;
}

signed main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n>>m;
for(i=1;i<=n;i++)
{
cin>>h[i]>>y[i];
}
for(i=1;i<=n;i++)
{
ans+=getg(i);
ans%=modp;
}
ans=(ans+modp)%modp;
cout<<ans<<endl;
return 0;
}

FFT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

using namespace std;

const int maxn=2100010;
const double pi=3.1415926535897;
int n,m,lmt;
int pla[maxn];

struct comp{
double x,y;
comp(double xx=0,double yy=0) {x=xx;y=yy;}
}a[maxn],b[maxn];

comp operator +(const comp &a,const comp &b){return comp(a.x+b.x,a.y+b.y);}
comp operator -(const comp &a,const comp &b){return comp(a.x-b.x,a.y-b.y);}
comp operator *(const comp &a,const comp &b){return comp(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}

void fft(comp *a,int t)
{
int i,j,len,p;
for(i=0;i<lmt;i++) if(i<pla[i]) swap(a[i],a[pla[i]]);
for(p=2;p<=lmt;p<<=1)
{
len=p>>1;
comp k=comp(cos(2.0*pi/p),1.0*t*sin(2.0*pi/p));
for(i=0;i<lmt;i+=p)
{
comp w=comp(1,0);
for(j=i;j<i+len;j++)
{
comp looker=a[j+len]*w;
a[j+len]=a[j]-looker;
a[j]=a[j]+looker;
w=w*k;
}
}
}
}

int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n>>m;
for(i=0;i<=n;i++) cin>>a[i].x;
for(i=0;i<=m;i++) cin>>b[i].x;
lmt=1;
while(lmt<=(n+m)) lmt<<=1;
for(i=0;i<lmt;i++) pla[i]=(pla[i>>1]>>1)|((i&1)?lmt>>1:0);
fft(a,1); fft(b,1);
for(i=0;i<lmt;i++) a[i]=a[i]*b[i];
fft(a,-1);
for(i=0;i<=n+m;i++) cout<<int((a[i].x)/lmt+0.49)<<" ";
cout<<endl;
return 0;
}

NTT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

#define int long long

using namespace std;

const int maxn=2100100;
const int modp=998244353;

int n,m,a[maxn],b[maxn];
int pla[maxn];
int lmt=1;

inline int ksm(int xx,int y)
{
long long x=1ll*xx;
long long ans=1ll;
while(y)
{
if(y&1) ans=(ans*x)%modp;
x=(x*x)%modp;
y>>=1;
}
return ans%modp;
}

inline void ntt(int *a,int t)
{
int i,len,p,j;
for(i=0;i<lmt;i++) if(i<pla[i]) swap(a[i],a[pla[i]]);
for(p=2;p<=lmt;p<<=1)
{
len=p>>1;
int k=ksm(t,(modp-1)/p);
for(i=0;i<lmt;i+=p)
{
int w=1;
for(j=i;j<i+len;j++)
{
int looker=(w*a[j+len])%modp;
a[j+len]=(a[j]-looker+modp)%modp;
a[j]=(a[j]+looker)%modp;
w=(w*k)%modp;
}
}
}
}

signed main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n>>m;
for(i=0;i<=n;i++) cin>>a[i];
for(i=0;i<=m;i++) cin>>b[i];
while(lmt<=(n+m)) lmt<<=1;
for(i=0;i<lmt;i++) pla[i]=(pla[i>>1]>>1)|((i&1)?lmt>>1:0);
ntt(a,3); ntt(b,3);
for(i=0;i<lmt;i++) a[i]=(1ll*a[i]*b[i])%modp;
ntt(a,ksm(3,modp-2));
lmt=ksm(lmt,modp-2);
for(i=0;i<=n+m;i++) cout<<(a[i]*lmt)%modp<<" ";
cout<<endl;
return 0;
}

矩阵

高斯消元

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<iomanip>
#include<algorithm>

using namespace std;

const int maxn=110;
const int eps=1e-7;


double a[maxn][maxn];
int n,m;


int main()
{
//ios::sync_with_stdio(false);
register int i,j,k;
cin>>n; m=n+1;
for(i=1;i<=n;i++) for(j=1;j<=m;j++) cin>>a[i][j];
for(i=1;i<=n;i++)
{
int mmx=i;
for(j=i+1;j<=n;j++) if(a[mmx][i]-a[j][i]<eps) mmx=j;
if(fabs(a[mmx][i])<=eps)
{
cout<<"No Solution"<<endl;
return 0;
}
for(j=1;j<=m;j++) swap(a[mmx][j],a[i][j]);
for(j=1;j<=n;j++)
{
if(i==j) continue;
double tmp=a[j][i]/a[i][i];
for(k=i+1;k<=m;k++)
{
a[j][k]-=a[i][k]*tmp;
}
}
}
for(i=1;i<=n;i++) printf("%.2lf\n",(a[i][m]/a[i][i]));
return 0;
}

矩阵求逆

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

#define int long long

using namespace std;

const int maxn=450;
const int modp=1e9+7;

int n,a[maxn][maxn],b[maxn][maxn];

int ksm(int x,int y)
{
int ans=1;
while(y)
{
if(y&1) ans=(ans*x)%modp;
x=(x*x)%modp;
y>>=1;
}
return ans;
}

inline void guass()
{
int i,j,k,l;
for(i=1;i<=n;i++)
{
int mmx=i;
for(j=i+1;j<=n;j++)
if(a[mmx][i]<a[j][i]) mmx=j;
for(j=1;j<=n;j++) swap(a[i][j],a[mmx][j]),swap(b[i][j],b[mmx][j]);
if(!a[i][i])
{
cout<<"No Solution";
return ;
}
int tmp=ksm(a[i][i],modp-2);
for(j=i;j<=n;j++) a[i][j]=(a[i][j]*tmp)%modp;
for(j=1;j<=n;j++) b[i][j]=(b[i][j]*tmp)%modp;
for(j=1;j<=n;j++)
{
if(i==j) continue;
int tmp=(a[j][i])%modp;
for(k=i;k<=n;k++) a[j][k]=((a[j][k]-a[i][k]*tmp)%modp+modp)%modp;
for(k=1;k<=n;k++) b[j][k]=((b[j][k]-b[i][k]*tmp)%modp+modp)%modp;
}
}
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
cout<<b[i][j]<<" ";
cout<<'\n';
}

}

signed main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
cin>>a[i][j];
for(i=1;i<=n;i++) b[i][i]=1;
guass();
return 0;
}

数论

原根

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

#define int long long
using namespace std;

const int maxn=1001000;

int pri[maxn],bj[maxn],cnt,phi[maxn];
int looker[maxn];
int vis[maxn];
int ys[30];
int q[maxn];
int n,m;

inline void getprime(int n)
{
int i,j;
looker[2]=looker[4]=phi[1]=1;
for(i=2;i<=n;i++)
{
if(!bj[i]) pri[++cnt]=i,phi[i]=i-1;
for(j=1;j<=cnt&&i*pri[j]<=n;j++)
{
bj[i*pri[j]]=1;
if(i%pri[j]==0)
{
phi[i*pri[j]]=pri[j]*phi[i];
break;
}
phi[i*pri[j]]=phi[i]*phi[pri[j]];
}
}
for(i=2;i<=cnt;i++)
for(j=1;j<=n;j*=pri[i])
looker[j]=1,looker[min(j*2,n+1)]=1;
}

inline int ksm(int x,int y,int modp)
{
int ans=1;
while(y)
{
if(y&1) ans=(ans*x)%modp;
x=(x*x)%modp;
y>>=1;
}
return ans;
}

signed main()
{
ios::sync_with_stdio(false);
register int i,j;
getprime(1000000);
int T;
cin>>T;
while(T--)
{
memset(vis,0,sizeof(vis));
memset(ys,0,sizeof(ys));
memset(q,0,sizeof(q));
int tot=0;
cin>>n>>m;
if(!looker[n]) { cout<<"0\n\n"; continue ;}
int tmp=phi[n];
for(i=1;pri[i]*pri[i]<=phi[n];i++)
{
if(tmp%pri[i]==0)
{
ys[++tot]=pri[i];
for(j=1;j*pri[i]<=n;j++) vis[j*pri[i]]=1;
}
while(tmp%pri[i]==0) tmp/=pri[i];
}
if(tmp>1)
{
ys[++tot]=tmp;
for(j=1;j*tmp<=n;j++) vis[j*tmp]=1;
}
j=1;
for(i=1;i<=n;i++)
{
while(ksm(i,phi[n],n)!=1) i++;
for(j=1;j<=tot&&ksm(i,phi[n]/ys[j],n)!=1;j++) ;
if(j>tot) break;
}
int mmn=i;
int k=mmn,sum=0;
for(i=1;i<=phi[n];i++,k=(k*mmn)%n)
{
if(!vis[i]) q[k]=1,sum++; else vis[i]=0;
}
cout<<sum<<"\n";
for(i=1,j=0;i<n;i++)
{
if(q[i]) j++;
if(j==m) cout<<i<<' ',j=0;
}
cout<<'\n';
}
return 0;
}

杂项

线性基

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

#define int long long

using namespace std;

int p[65],l[65],ans;
int n,m;

signed main()
{
ios::sync_with_stdio(false);
register int i,j;
for(i=0;i<=60;i++) l[i]=1ll<<i;
cin>>n;
int tmp;
for(i=1;i<=n;i++)
{
cin>>tmp;
for(j=60;j>=0;j--) if(l[j]&tmp)
{
if(p[j]) tmp^=p[j];
else
{
p[j]=tmp;
break;
}
}
}
for(i=60;i>=0;i--) if((ans^p[i])>ans) ans^=p[i];
cout<<ans<<endl;
return 0;
}

数据结构

线段树

主席树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include<stdio.h>
#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

#define ls(i) t[(i)].l
#define rs(i) t[(i)].r

using namespace std;

const int maxn=100010;

int cnt,n,m;
int a[maxn],rt[maxn];
int b[maxn];

struct tree{
int l,r,sum;
}t[maxn*20];

struct orztree{

inline void pushup(int i)
{
t[i].sum=t[ls(i)].sum+t[rs(i)].sum;
}

void build_tree(int i,int l,int r)
{
if(l==r) return ;
t[i].l=++cnt; t[i].r=++cnt;
int mid=(l+r)>>1;
build_tree(ls(i),l,mid);
build_tree(rs(i),mid+1,r);
}

void change_tree(int looker,int i,int l,int r,int x)
{
t[i].sum=t[looker].sum+1;
t[i].l=t[looker].l; t[i].r=t[looker].r;
if(l==r) return ;
int mid=(l+r)>>1;
if(x<=mid) t[i].l=++cnt,change_tree(ls(looker),ls(i),l,mid,x);
else t[i].r=++cnt,change_tree(rs(looker),rs(i),mid+1,r,x);
}

int ask_kth_tree(int looker,int i,int l,int r,int k)
{
int tmp=t[ls(i)].sum-t[ls(looker)].sum;
if(l==r) return b[l];
int mid=(l+r)>>1;
if(k>tmp) return ask_kth_tree(rs(looker),rs(i),mid+1,r,k-tmp);
else return ask_kth_tree(ls(looker),ls(i),l,mid,k);
}

}st;

int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n>>m;
for(i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
sort(b+1,b+n+1);
int tot=unique(b+1,b+n+1)-b-1;
for(i=1;i<=n;i++) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
rt[0]=++cnt; st.build_tree(rt[0],1,n);
for(i=1;i<=n;i++) rt[i]=++cnt,st.change_tree(rt[i-1],rt[i],1,n,a[i]);
int t1,t2,t3;
for(i=1;i<=m;i++)
{
cin>>t1>>t2>>t3;
cout<<st.ask_kth_tree(rt[t1-1],rt[t2],1,n,t3)<<"\n";
}
return 0;
}

最短路

dijkstra

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include<utility>
#include<queue>
#include<iostream>
#include<cmath>
#include<queue>
#include<cstring>
#include<cstdio>
using namespace std;
priority_queue<pair<int,int> > q;
struct edge{
int next,to,dis;
};
edge e[200800];
int head[1000010];
int d[100800],vis[100800];
int s;
int size,n,m;
void addedge(int next,int to,int dis)
{
e[++size].next=head[next];
e[size].to=to;
e[size].dis=dis;
head[next]=size;
}
void dij(int start)
{
memset(d,0x3f,sizeof(d));
memset(vis,0,sizeof(vis));
d[start]=0;
q.push(make_pair(0,start));
while(!q.empty())
{
int t=q.top().second;
q.pop();
if(vis[t]) continue;
vis[t]=1;
for(int i=head[t];i;i=e[i].next)
{
int y=e[i].to;
int k=e[i].dis;
if(d[y]>d[t]+k)
{
d[y]=d[t]+k;
q.push(make_pair(-d[y],y));
}
}
}
}
int main()
{

cin>>n>>m>>s;
for(int i=1;i<=m;i++)
{
int tx,ty,tdis;
scanf("%d %d %d",&tx,&ty,&tdis);
addedge(tx,ty,tdis);
}
dij(s);
for(int i=1;i<=n;i++)
printf("%d ",d[i]);
return 0;
}

强连通分量

tarjan

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void tarjan(int t)
{
dfn[t]=low[t]=++bl;
s.push(t);
ins[t]=1;
int i,j;
for(i=head[t];i;i=e[i].next)
{
j=e[i].to;
if(!dfn[j])
{
tarjan(j);
low[t]=min(low[t],low[j]);
}
else if(ins[j]) low[t]=min(dfn[j],low[t]);
}
j=0;
if(dfn[t]==low[t])
{
cnt++;
while(t!=j)
{
j=s.top();
s.pop();
ins[j]=0;
bd[j]=cnt;
}
}
}

网络流

dinic

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

using namespace std;

const int maxn=20020;

int head[maxn],size=1,st,ed,ans,n,m;
int dep[maxn],vis[maxn];
int nt[maxn];

struct edge{
int next,to,dis;
int flow;
}e[maxn*10];

inline void addedge(int next,int to,int flow)
{
e[++size].to=to;
e[size].next=head[next];
e[size].flow=flow;
head[next]=size;
}

inline int bfs(int st)
{
queue <int> q;
memset(vis,0,sizeof(vis));
memset(dep,0,sizeof(dep));
q.push(st);
vis[st]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
int i,j,k;
for(i=head[t];i;i=e[i].next)
{
j=e[i].to;
k=e[i].flow;
if(vis[j]||dep[j]||k<=0) continue;
dep[j]=dep[t]+1;q.push(j);
vis[j]=1;
}
}
return vis[ed];
}

int dfs(int t,int nowt)
{
if(t==ed||!nowt) return nowt;
int tot=0;
int j,k;
for(int &i=nt[t];i;i=e[i].next)
{
j=e[i].to;
k=e[i].flow;
if(k>0&&dep[j]==dep[t]+1)
{
int f=dfs(j,min(k,nowt-tot));
e[i].flow-=f;
e[i^1].flow+=f;
tot+=f;
if(nowt==tot) return tot;
}
}
return tot;

}

void dinic()
{
int i;
while(bfs(st))
{
for(i=1;i<=n;i++) nt[i]=head[i];
ans+=dfs(st,0x3f3f3f3f);
}
}


int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n>>m>>st>>ed;
int t1,t2,t3;
for(i=1;i<=m;i++)
{
cin>>t1>>t2>>t3;
addedge(t1,t2,t3);
addedge(t2,t1,0);
}
dinic();
cout<<ans<<endl;
return 0;

}

ISAP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<vector>
#include<set>
#include<map>
#include<algorithm>

using namespace std;

const int maxn=20020;

int head[maxn],size=1,st,ed,ans,n,m;
int dep[maxn],vis[maxn];
int nt[maxn];

struct edge{
int next,to,dis;
int flow;
}e[maxn*10];

inline void addedge(int next,int to,int flow)
{
e[++size].to=to;
e[size].next=head[next];
e[size].flow=flow;
head[next]=size;
}

inline int bfs(int st)
{
queue <int> q;
memset(vis,0,sizeof(vis));
memset(dep,0,sizeof(dep));
q.push(st);
vis[st]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
int i,j,k;
for(i=head[t];i;i=e[i].next)
{
j=e[i].to;
k=e[i].flow;
if(vis[j]||dep[j]||k<=0) continue;
dep[j]=dep[t]+1;q.push(j);
vis[j]=1;
}
}
return vis[ed];
}

int dfs(int t,int nowt)
{
if(t==ed||!nowt) return nowt;
int tot=0;
int j,k;
for(int &i=nt[t];i;i=e[i].next)
{
j=e[i].to;
k=e[i].flow;
if(k>0&&dep[j]==dep[t]+1)
{
int f=dfs(j,min(k,nowt-tot));
e[i].flow-=f;
e[i^1].flow+=f;
tot+=f;
if(nowt==tot) return tot;
}
}
return tot;

}

void dinic()
{
int i;
while(bfs(st))
{
for(i=1;i<=n;i++) nt[i]=head[i];
ans+=dfs(st,0x3f3f3f3f);
}
}


int main()
{
ios::sync_with_stdio(false);
register int i,j;
cin>>n>>m>>st>>ed;
int t1,t2,t3;
for(i=1;i<=m;i++)
{
cin>>t1>>t2>>t3;
addedge(t1,t2,t3);
addedge(t2,t1,0);
}
dinic();
cout<<ans<<endl;
return 0;

}

树剖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void dfs1(int nownode,int father)
{
sz[nownode]=1;
f[nownode]=father;
dep[nownode]=dep[father]+1;
int i,j;
for(i=head[nownode];i;i=e[i].next)
{
j=e[i].to;
if(j==father) continue;
dfs1(j,nownode);
sz[nownode]+=sz[j];
if(sz[son[nownode]]<sz[j]) son[nownode]=j;
}
}

void dfs2(int nownode,int topnode)
{
top[nownode]=topnode;
id[nownode]=++cnt;
rk[cnt]=nownode;
if(!son[nownode]) return ;
dfs2(son[nownode],topnode);
int i,j;
for(i=head[nownode];i;i=e[i].next)
{
j=e[i].to;
if(j==son[nownode]||j==f[nownode]) continue;
dfs2(j,j);
}
}

inline int getlca(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=f[top[x]];
}
if(id[x]>id[y]) swap(x,y);
return x;
}