读入优化:
int GET()
{
int x=0,f=1;
char c;
c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
return x*f;
}
快速幂:
int ksm(int a,int b,int c)
{
int ans=1;
a=a%c;
while (b>0)
{
if (b&1) ans=(ans*a)%c;
b=b/2;
a=(a*a)%c;
}
return ans;
}
RMQ:
int seat_rmq(int i,int j)
{
int k=log(i+j-1)/log(2);
return min(f[i][k],f[i-(1<<k)+1][k]);
}
while (tmp<=n)
{
tmp*=2;
k++;
}
for (j=1;j<=k;j++)
for (i=1;i<=n;i++)
if (i+(1<<(i-1))-1<=n)
f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
tarjan:
void tarjan(int u)
{
int i;
low[u]=dfn[u]=++insex;
instack[u]=true;
stack[++tot]=u;
for (i=head[u];i;i=e[i].next)
{
int v=e[i].to;
if (!dfn[v])
{
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if (instack[v])
{
low[u]=min(low[u],dfn[v]);
}
}
if (low[u]==dfn[u])
{
int tmp=0;
while (tmp!=u)
{
tmp=stack[tot--];
instack[tmp]=false;
}
}
}
void slove()
{
int i;
memset(dfn,0,sizeof(dfn));
for (i=1;i<=n;i++)
if (!dfn[i])
tarjan(i);
}
邻接表:
void add(int from,int to)
{
++e_num;
e[e_num].from=from;
e[e_num].to=to;
e[e_num].next=head[from];
head[from]=e_num;
}
Dijkstra:
memset(flag,false,sizeof(flag));
c[1]=0;
for (i=1;i<=n;i++)
{
minn=maxx;
k=0;
for (j=1;j<=n;j++)
if ((!flag[j])&&(c[j]<minn))
{
minn=c[j];
k=j;
}
if (k==0) break;
flag[k]=true;
for (j=1;j<=n;j++)
{
if (c[k]+f[k][j]<c[j])
c[j]=c[k]+f[k][j];
}
}
floyed
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
if ((i!=j)&&(j!=k)&&(i!=k))
f[i][j]=min(f[i][j],f[i][k]+f[k][j]);
SPFA:
void SPFA()
{
memset(vis,false,sizeof(vis));
for (i=1;i<=n;i++)
dis[i]=maxx;
dis[1]=0;
q[1]=1;
vis[1]=true;
int top=0,tail=1;
while (top<tail)
{
top++;
int u=q[top];
vis[u]=false;
for (i=head[u];i;i=e[i].next)
{
if (dis[u]+e[i].dis<dis[e[i].to])
{
dis[e[i].to]=dis[u]+e[i].dis;
if (!vis[e[i].to])
{
tail++;
q[tail]=e[i].to;
vis[e[i].to]=true;
}
}
}
}
}
数据生成器:
#include<bits/stdc++.h>
using namespace std;
#define random(a,b) ((a)+rand()%((b)-(a)+1))
stringstream ss;
int main( int argc, char *argv[] )
{
int seed=time(NULL);
if(argc)
{
ss.clear();
ss<<argv[1];
ss>>seed;
}
srand(seed);
//以上为随机数初始化,请勿修改
//random(a,b)生成[a,b]的随机整数
//以下写你自己的数据生成代码
printf("\n");
return 0;
}
辗转相除法(欧几里得):
void gcd(int a,int b)
{
if (b) return gcd(b,a%b);
else return a;
扩展欧几里得:
int exgcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
int r=exgcd(b,a%b,x,y);
int t=x;
x=y;
y=t-a/b*y;
return r;
}
Eratosthenes筛法:
void eratosthenes_sieve(int n)
{
totPrimes = 0;
memset(flag, 0, sizeof(flag));
int sqrtn = sqrt(n + 0.5);
for (int i = 2; i <= sqrtn; i++) {
if (!flag[i]) {
primes[totPrimes++] = i;
for (int j = i * i; j <= n; j += i) {
flag[j] = true;
}
}
}
for (int i = sqrtn + 1; i <= n; i++) {
if (!flag[i])
primes[++totPrimes] = i;
}
}
欧拉筛法:
void euler_sieve(int n)
{
totPrimes = 0;
memset(flag, 0, sizeof(flag));
for (int i = 2; i <= n; i++) {
if (!flag[i])
primes[totPrimes++] = i;
for (int j = 0; i * primes[j] <= n; j++) {
flag[i*primes[j]] = true;
if (i % primes[j] == 0)
break;
}
}
}
LCA:
void add(int from,int to)
{
++e_num;
e[e_num].to=to;
e[e_num].next=head[from];
head[from]=e_num;
}
void rmq(int t)
{
int i;
for (i=1;i<=20;i++)
{
if (deep[t]<(1<<i))
break;
f[t][i]=f[f[t][i-1]][i-1];
}
vis[t]=true;
for (i=head[t];i;i=e[i].next)
if (!vis[e[i].to])
{
deep[e[i].to]=deep[t]+1;
f[e[i].to][0]=t;
rmq(e[i].to);
}
}
int lca(int x,int y)
{
int i;
if (deep[x]<deep[y])
{
swap(x,y);
}
for (i=20;i>=0;i--)
{
if (deep[x]-deep[y]>=(1<<i))
x=f[x][i];
}
if (x==y) return x;
int u=0;
while (deep[x]>=(1<<u)) u++;
for (i=u;i>=0;i--)
if (f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
int main()
{
int i,x,y;
scanf("%d%d",&n,&m);
for (i=1;i<=n-1;i++)
{
x=get();y=get();
add(x,y);add(y,x);
}
rmq(s);
for (i=1;i<=m;i++)
{
x=get();y=get();
printf("%d\n",lca(x,y));
}
}