暗的连锁 POJ3417

Posted zw130-lzr-blogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了暗的连锁 POJ3417相关的知识,希望对你有一定的参考价值。

树上边的差分,给每个点赋值为0,对于非树边(x,y)x,y权值+1,lca(x,y)-=2,再dfs

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define MN 200050
using namespace std;
int n,m,cnt,head[MN],ans[MN],dfn[MN],num[MN];
int f[MN][21];
int lg[MN];
struct tu
int v,nxt;
e[MN];
void add(int u,int v)
e[++cnt].v=v;
e[cnt].nxt=head[u];
head[u]=cnt;

void dfs(int now,int fa)
dfn[now]=dfn[fa]+1;
f[now][0]=fa;
for(int i=1;(1<<i)<=dfn[now];i++)
f[now][i]=f[f[now][i-1]][i-1];
for(int i=head[now];i;i=e[i].nxt)
if(e[i].v!=fa)dfs(e[i].v,now);


int lca(int x,int y)
if(dfn[x]<dfn[y])swap(x,y);
while(dfn[x]>dfn[y])
x=f[x][lg[dfn[x]-dfn[y]]];

if(x==y)return x;
for(int k=lg[dfn[x]];k>=0;k--)
if(f[x][k]!=f[y][k])
x=f[x][k],y=f[y][k];
return f[x][0];

void search(int now,int fa)
ans[now]=num[now];
for(int i=head[now];i;i=e[i].nxt)
if(e[i].v!=fa)
search(e[i].v,now);
ans[now]+=ans[e[i].v]; //前缀和所以加儿子权                            



int main()
int sum=0;
scanf("%d%d",&n,&m);
lg[0]=-1;
for(int i=1;i<=n;i++)
lg[i]=lg[i>>1]+1;
for(int i=1;i<=n-1;i++)
int a,b;
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);

dfs(1,0);
for(int i=1;i<=m;i++)
int a,b;
scanf("%d%d",&a,&b);
num[a]++;num[b]++;num[lca(a,b)]-=2;

search(1,0);
for(int i=2;i<=n;i++)
if(!ans[i])sum+=m;
if(ans[i]==1)sum++;

printf("%d",sum);

return 0;

若有错误请指出

以上是关于暗的连锁 POJ3417的主要内容,如果未能解决你的问题,请参考以下文章

1553:例 2暗的连锁

一本通1553例 2暗的连锁

题解一本通1553:例 2暗的连锁

loj 10131 暗的连锁

poj3417 闇の連鎖 树上差分By cellur925

倍增法求lca:暗的连锁