zoukankan      html  css  js  c++  java
  • luoguP4103 [HEOI2014]大工程

    题意

    建出虚树DP。
    (f[i])表示i的子树的第一问答案,(minn[i])表示(i)的子树中到(i)最近的关键点,(maxx[i])表示(i)的子树中到i距离最远的关键点,(size[i])表示(i)子树中的关键点个数。

    (f[x]=sumlimits_{yin son_x}f[y]+size[y]*(tot-size[y])*w)

    (minn)(maxx)就类似树的直径。

    code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=1000010;
    const ll inf=1e18;
    int n,m,cnt,t,top,tot,tim;
    int head[maxn],size[maxn],a[maxn],dep[maxn],sta[maxn],dfn[maxn];
    int f[maxn][25];
    ll ans1,ans2;
    ll g[maxn],maxx[maxn],minn[maxn];
    bool check[maxn];
    struct edge{int to,nxt,dis;}e[maxn<<1];
    inline int read()
    {
    	char c=getchar();int res=0,f=1;
    	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    	while(c>='0'&&c<='9')res=res*10+c-'0',c=getchar();
    	return res*f;
    }
    inline bool cmp(int x,int y){return dfn[x]<dfn[y];}
    inline void add(int u,int v,int w)
    {
    	e[++cnt].nxt=head[u];
    	head[u]=cnt;
    	e[cnt].to=v;
    	e[cnt].dis=w;
    }
    void dfs_pre(int x,int fa)
    {
    	dep[x]=dep[fa]+1;dfn[x]=++tim;
    	for(int i=1;i<=t;i++)f[x][i]=f[f[x][i-1]][i-1];
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		if(y==fa)continue;
    		f[y][0]=x;dfs_pre(y,x);
    	}
    }
    inline int lca(int x,int y)
    {
    	if(dep[x]>dep[y])swap(x,y);
    	for(int i=t;~i;i--)if(dep[f[y][i]]>=dep[x])y=f[y][i];
    	if(x==y)return x;
    	for(int i=t;~i;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    inline int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
    void dfs(int x)
    {
    	//cerr<<"test::"<<x<<endl;
    	g[x]=0;
    	maxx[x]=-inf,minn[x]=inf;size[x]=0;
    	if(check[x])size[x]=1,minn[x]=0,maxx[x]=0;
    	for(int i=head[x];i;i=e[i].nxt)
    	{
    		int y=e[i].to;
    		dfs(y);size[x]+=size[y];
    		g[x]+=g[y]+1ll*e[i].dis*size[y]*(tot-size[y]);
    		ans1=min(ans1,minn[x]+minn[y]+e[i].dis);
    		minn[x]=min(minn[x],minn[y]+e[i].dis);
    		ans2=max(ans2,maxx[x]+maxx[y]+e[i].dis);
    		maxx[x]=max(maxx[x],maxx[y]+e[i].dis);
    	}
    }
    void solve()
    {
    	cnt=0;ans1=inf;ans2=-inf;
    	tot=read();
    	for(int i=1;i<=tot;i++)a[i]=read(),check[a[i]]=1;
    	sort(a+1,a+tot+1,cmp);
    	sta[top=1]=1,head[1]=0;
    	for(int i=1;i<=tot;i++)
    	{
    		if(a[i]==1)continue;
    		int x=lca(a[i],sta[top]);
    		if(x!=sta[top])
    		{
    			while(top>1&&dfn[sta[top-1]]>dfn[x])add(sta[top-1],sta[top],dis(sta[top-1],sta[top])),top--;
    			if(x!=sta[top-1])head[x]=0,add(x,sta[top],dis(x,sta[top])),sta[top]=x;
    			else add(x,sta[top],dis(x,sta[top])),top--;
    		}
    		head[a[i]]=0;sta[++top]=a[i];
    	}
    	for(int i=1;i<top;i++)add(sta[i],sta[i+1],dis(sta[i],sta[i+1]));
    	dfs(1);
    	printf("%lld %lld %lld
    ",g[1],ans1,ans2);
    	for(int i=1;i<=tot;i++)check[a[i]]=0;
    }
    int main()
    {
    	//freopen("test.in","r",stdin);
    	//freopen("test.out","w",stdout);
    	n=read();t=(int)log2(n)+1;
    	for(int i=1;i<n;i++)
    	{
    		int u=read(),v=read();
    		add(u,v,1),add(v,u,1);
    	}
    	dfs_pre(1,0);
    	m=read();
    	for(int i=1;i<=m;i++)solve();
    	return 0;
    } 
    
  • 相关阅读:
    Delphi XE2 之 FireMonkey 入门(16) 滤镜: 实例测试
    Delphi XE2 之 FireMonkey 入门(20) TStyleBook(皮肤、样式相关)
    Delphi XE2 之 FireMonkey 入门(18) TLang(多语言切换的实现)
    Delphi XE2 之 FireMonkey 入门(15) 滤镜: 获取滤镜信息
    ASP.NET中常用功能代码总结(7)——利用Jmail发送和接收邮件
    使用.NET Remoting开发分布式应用——基于租约的生存期
    一个SOA时代的到来,看CSDN新闻有感
    .NET设计模式(3):抽象工厂模式(Abstract Factory)
    ASP.NET中常用功能代码总结(3)——上传图片到数据库
    人的一生 有三件事情不能等
  • 原文地址:https://www.cnblogs.com/nofind/p/11977172.html
Copyright © 2011-2022 走看看