列表

详情


NC16519. 城市漫游

描述

    在点点和评评的世界里有一个城市,城市是一个树形结构,由n个节点组成,有n-1条双向边把这些节点连在了一起(即在任意两个节点AB之间都存在从A到B的路径)。每条边都有一个边权,表示通过这条边需要的时间。
    现在点点和评评想要从他们所在的S点到T点参加会议,他们想要在过程中体会旅途的乐趣,即好好欣赏每条边上的风景。详细地说,对于每条边,都有一个值l,l表示在从S点到T点的过程中,最少需要经过这条边的次数。因为会期将至,所以点点和评评想要在看够风景的情况下,花费尽可能少的时间。
    点点和评评一共想询问m组这样的S和T,每组询问单独考虑,对于某一组特定的询问,他们想知道最少需要花费的时间。

输入描述

第一行一个整数n(1 ≤ n ≤ 100,000)表示点数。
接下来n-1行,每行四个整数x, y, z, l(1 ≤ x, y ≤ n, 1 ≤ z, l ≤ 1,000,000,000),表示从x到y之间有一条边权为z的边,并且这条边至少要经过l次。
数据保证没有重边和自环。
接下来一个整数m(1 ≤ m ≤ 100,000)表示询问组数。
接下来m行,每行两个整数S, T(1 ≤ S, T ≤ n)表示一组询问。

输出描述

输出m行,每行一个整数表示答案,因为答案可能很大,请输出答案 mod 1,000,000,007的值。

示例1

输入:

3
1 2 10 1  
2 3 20 2
2
1 3
3 2

输出:

70
80

说明:

路径为:
1->2->3->2->3
3->2->1->2->3->2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 339ms, 内存消耗: 19160K, 提交时间: 2018-08-02 09:35:24

#include<cstdio>
#include<vector>
using namespace std;
struct edge
{
	int x,y,z,l;
}e[100005];
struct p
{
	int s,t,ans;
}ta[100005];
int n,i,m,dp[2][100005],dsu[100005],vis[100005],ans=0;
const int mod=1e9+7;
vector<int> s[100005];
vector<int> ss[100005];
int other1(int p,int id){return e[id].x==p?e[id].y:e[id].x;}
int other2(int p,int id){return ta[id].s==p?ta[id].t:ta[id].s;}
int get(int p){return dsu[p]==p?p:dsu[p]=get(dsu[p]);}
void dfs(int p)
{
	int i,v,u,f;
	edge h;
	vis[p]=1;
	for(i=0;i<ss[p].size();i++)
	{
		v=ss[p][i];
		u=other2(p,v);
		if(vis[u]==0)continue;
		f=get(u);
		ta[v].ans=((1LL*ans+1LL*dp[0][u]+1LL*dp[0][p]-dp[1][u]-dp[1][p]-2LL*dp[0][f]+2LL*dp[1][f])%mod+mod)%mod;
	}
	for(i=0;i<s[p].size();i++)
	{
		v=s[p][i];
		u=other1(p,v);
		if(vis[u])continue;
		dp[0][u]=dp[0][p];
		dp[1][u]=dp[1][p];
		if(e[v].l%2)dp[1][u]=(dp[1][u]+e[v].z)%mod;
		else dp[0][u]=(dp[0][u]+e[v].z)%mod;
		dfs(u);
		dsu[u]=p;
	}
}
int main()
{
	scanf("%d",&n);
	for(i=1;i<=n;i++)dsu[i]=i;
	for(i=1;i<n;i++)
	{
		scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].z,&e[i].l);
		s[e[i].x].push_back(i);
		s[e[i].y].push_back(i);
		ans=(ans+1LL*e[i].z*(e[i].l+e[i].l%2))%mod;
	}
	scanf("%d",&m);
	for(i=1;i<=m;i++)
	{
		scanf("%d%d",&ta[i].s,&ta[i].t);
		if(ta[i].s==ta[i].t)ta[i].ans=ans;
		else
		{
			ss[ta[i].s].push_back(i);
			ss[ta[i].t].push_back(i);
		}
	}
	dfs(1);
	for(i=1;i<=m;i++)printf("%d\n",ta[i].ans);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 190ms, 内存消耗: 11108K, 提交时间: 2020-03-29 12:02:56

#include<bits/stdc++.h>
using namespace std;
const int N=100010;
const int mod=1000000007;
int n,m,s,dep[N],fa[N],top[N],siz[N];
int head[N<<1],to[N<<1],nxt[N<<1],num[N<<1],e;
long long dis[N],w[N<<1];
inline void add(int u,int v,long long z,int l)
{
	to[++e]=v,w[e]=z,num[e]=l,nxt[e]=head[u],head[u]=e;
}
void dfs(int u)
{
	int i,maxs=0,son=0;
	top[u]=u,siz[u]=1;
	for(i=head[u];i;i=nxt[i])
	{
		int v=to[i];
		if(v==fa[u]) continue;
		fa[v]=u,dep[v]=dep[u]+1;
		dis[v]=(dis[u]+((num[i]&1)?1:-1)*w[i])%mod;
		dfs(v);
		siz[u]+=siz[v];
		if(siz[v]>maxs) maxs=siz[son=v];
	}
	if(son) top[son]=u;
}
int find(int u)
{
	return top[u]=top[u]==u?u:find(top[u]);
}
int LCA(int u,int v)
{
	if(find(u)!=find(v))
	return dep[top[u]]>dep[top[v]]?LCA(fa[top[u]],v):LCA(u,fa[top[v]]);
	else return dep[u]>dep[v]?v:u;
}
int main()
{
	scanf("%d",&n);
	int u,v,l;
	long long z;
	long long sum=0,ans;
	for(int i=1;i<n;++i)
	{
		scanf("%d%d%lld%d",&u,&v,&z,&l),add(u,v,z,l),add(v,u,z,l);
		sum=(sum+(l+(l&1))*z%mod)%mod;
	}
	scanf("%d",&m);
	dis[1]=0,dfs(1);
	while(m--)
	{
		scanf("%d%d",&u,&v);
		int lca=LCA(u,v);
		printf("%lld\n",((sum+2*dis[lca]-dis[u]-dis[v])%mod+mod)%mod);
	}
	return 0;
}

上一题