树上查分 暗之链锁

      传送门

        朴素版LCA就能过。。标程是树上查分,但数据很水。

     标记每一条树边被虚边覆盖的次数,只有一次或零次时,砍此边才能满足,一次时只有一种,零次时有m种。

     

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 100000
using namespace std;
int n,m,adj[N+5],ans=0,e=0;
int f[N+5],dep[N+5],a[N*2+5],bian[N+5];
struct node 
{
	int v,next;
} lu[N*2+20];
void add(int u,int v)
{
	lu[++e].v=v;lu[e].next=adj[u];adj[u]=e;
}
int read()
{
	int sum=0;char x=getchar();
	while(x<'0'||x>'9')x=getchar();
	while(x>='0'&&x<='9')sum=sum*10+x-'0',x=getchar();
	return sum;
}
void dfs(int x,int fa)
{
	f[x]=fa;
	for(int i=adj[x];i;i=lu[i].next)
	{
		int to=lu[i].v;
		if(to!=f[x])
		{
		    bian[to]=i;
			dep[to]=dep[x]+1;
			dfs(to,x);
		}
	}
}
void jia(int x,int y)
{
	while(x!=y)
	{
		if(dep[x]<dep[y])swap(x,y);
		a[bian[x]]++;
		x=f[x];
	}
}
void zhao(int x)
{
	for(int i=adj[x];i;i=lu[i].next)
	if(lu[i].v!=f[x])
	{
		if(!a[i])
		   ans+=m;
		else
		   if(a[i]==1)
		      ans+=1;
		zhao(lu[i].v);
	}
}
int yjn()
{
	freopen("yam.in","r",stdin);
	freopen("yam.out","w",stdout);
	n=read();m=read();
	int x,y;
	for(int i=1;i<n;i++)
	{
		x=read();y=read();
		add(x,y);
		add(y,x);
	}
	dfs(1,0);
	for(int i=1;i<=m;i++)
	{
		x=read();y=read();
		jia(x,y);
	}
	zhao(1);
	printf("%d",ans);
	//for(int i=1;i<=n;i++)
	//    cout<<bian[i]<<" "<<a[bian[i]]<<endl;
}
int qty=yjn();
int main(){;}

原文地址:https://www.cnblogs.com/QTY2001/p/7632775.html