洛谷-【图论2-1】树4

P5588 小猪佩奇爬树

题目描述

佩奇和乔治在爬♂树。

给定 n 个节点的树 T(V,E),第 i 个节点的颜色为 wi​,保证有 1≤wi​≤n。

对于 1≤i≤n,分别输出有多少对点对 (u,v),满足 u<v,且恰好经过所有颜色为 i 的节点,对于节点颜色不为 i 的其他节点,经过或不经过均可。

树上路径 (u,v) 定义为序列 {f},满足 f1​=u,f∣f∣​=v,且 ∀1≤i<∣f∣,T 中均存在边 (fi​,fi+1​),且 {f} 中无重复元素,能够证明对于任意点对 (u,v),其树上路径唯一。

输入格式

第一行 1 个正整数,表示 n 。

第二行 n 个正整数,第 i 个正整数表示 wi​。

之后 n−1 行,每行 2 个正整数 u,v,表示 T 中存在边 (u,v)。

输出格式

共 n 行,每行 1 个正整数,第 i 行输出包含所有颜色为 i 的节点的路径个数。

输入输出样例

输入 #1复制

复制代码
4
1 2 2 3
1 2
2 3
3 4

输出 #1复制

复制代码
3
4
3
6

输入 #2复制

复制代码
10
9 7 4 2 3 4 4 5 8 5
2 1
3 2
4 2
5 2
6 4
7 4
8 1
9 4
10 4

输出 #2复制

复制代码
45
35
9
0
1
45
34
9
17
45

说明/提示

对于第一组样例而言。

对于颜色 1,点对 (1,2),(1,3),(1,4) 满足条件。

对于颜色 2,点对 (1,3),(1,4),(2,3),(2,4) 满足条件。

对于颜色 3,点对 (1,4),(2,4),(3,4) 满足条件。

对于颜色 4,由于图中没有颜色为 4 的节点,所以所有点对均满足条件。

数据范围

对于 40% 的数据,n≤102。

对于 60% 的数据,n≤103。

对于 100% 的数据,n≤106。

实现代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
struct q
{
	int dep,num;
};
q w[1000010];
int x,y,n[1000010],dep[1000010],l,db[2000010],nxt[2000010],len[2000010];
int f[1000010][21],fath,o,oo,fathe[1000010],ll,h,hh;
long long a,s,sn[1000010],v[1000010],vv;
vector<int> t[1000010];
bool ff;
template <typename T> inline void read(T &x)
{
	x=0;char c=getchar();bool flg=0;
	for (;!isdigit(c);c=getchar()) if (c=='-') flg=1;
	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
	if (flg) x=-x;
}
inline void write(long long x)
{
	if (x<0)
	{
		putchar('-');
		x=-x;
	}
	if (x>=10) write(x/10);
	putchar(x%10+48);
}
inline void writeln(long long x)
{
	write(x);
	puts("");
}
bool cmp(q p,q pp)
{
	return p.dep>pp.dep;
}
void wrk(int fa,int u)
{
	dep[u]=dep[fa]+1;fathe[u]=fa;
	for (int i=0;i<=19;i++)
	f[u][i+1]=f[f[u][i]][i];
	int k=len[u];
	while (k)
	{
		if (db[k]==fa)
		{
			k=nxt[k];
			continue;
		}
		f[db[k]][0]=u;
		wrk(u,db[k]);
		sn[u]+=sn[db[k]];
		k=nxt[k];
	}
}
int lca(int x,int y)
{
	if (dep[x]<dep[y]) swap(x,y);
	for (int i=20;i>=0;i--)
	{
		if (dep[f[x][i]]>=dep[y]) x=f[x][i];
		if (x==y) return x;
	}
	for (int i=20;i>=0;i--)
	{
		if (f[x][i]!=f[y][i])
		{
			x=f[x][i];
			y=f[y][i];			
		}
	}
	return f[x][0];
}
int main(){
	read(a);
	for (int i=1;i<=a;i++)
	{
		read(n[i]);
		t[n[i]].push_back(i);
	}
	for (int i=1;i<a;i++)
	{
		read(x);read(y);
		db[i*2-1]=y;
		nxt[i*2-1]=len[x];
		len[x]=i*2-1;
		db[i*2]=x;
		nxt[i*2]=len[y];
		len[y]=i*2;		
	}
	for (int i=1;i<=a;i++) sn[i]=1;
	wrk(0,1);
	for (int i=1;i<=a;i++)
	{
		l=0;
		for (int j=0;j<t[i].size();j++)
		{
			l++;
			w[l].num=t[i][j];
			w[l].dep=dep[w[l].num];
		}
		if (l==1)
		{
			int k=len[w[l].num];ll=0;
			while (k)
			{
				if (db[k]==fathe[w[l].num])
				{
					k=nxt[k];
					continue;
				}
				ll++;
				v[ll]=sn[db[k]];
				k=nxt[k];
			}
			vv=(sn[w[l].num]-1)*(a-sn[w[l].num])+a-1;
			for (int j=1;j<=ll;j++)
				for (int m=j+1;m<=ll;m++)
				vv+=v[j]*v[m];
			writeln(vv);
			continue;
		}
		if (l==0)
		{
			writeln((a*(a-1))/2);
			continue;
		}
		sort(w+1,w+l+1,cmp);
		hh=0;
		for (int j=2;j<=l;j++)
		{
			fath=lca(w[1].num,w[j].num);
			if (fath!=w[j].num) 
			{
				hh=j;
				break;
			}		
		}
		ff=0;
		if (hh!=0)
		for (int j=3;j<=l;j++)
		{
			o=lca(w[j].num,w[1].num);oo=lca(w[j].num,w[hh].num);
			if (((o==w[j].num)||(oo==w[j].num))&&(dep[w[j].num]>=dep[fath])) continue;
			ff=1;break;
		}
		if (ff==0)
		{
			if (hh==0)
			{
				int k=w[1].num;h=w[1].num;
				while (fathe[k]!=w[l].num)
				{
					k=fathe[k];
					h=k;
				}
				writeln(sn[w[1].num]*(a-sn[w[l].num]+sn[w[l].num]-sn[h]));				
			}
			else writeln(sn[w[1].num]*sn[w[hh].num]);
		}
		else writeln(0);
	}
	return 0;
}

P5536 【XR-3】核心城市

题目描述

X 国有 n 座城市,n−1 条长度为 1 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树。

X 国国王决定将 k 座城市钦定为 X 国的核心城市,其余城市为非核心城市。这 k 座核心城市需满足以下两个条件:

  1. 这 k 座城市可以通过道路,在不经过非核心城市的情况下两两相互到达。
  2. 定义某个非核心城市与这 k 座核心城市的距离为,这座城市与 k 座核心城市的距离的最小值。

为了衡量交通状况,国王发明了交通拥堵度,它为所有非核心城市与核心城市的距离中的最大值。

问题来了,如何安排核心城市才能使交通拥堵度最小呢?请输出满足条件的最小交通拥堵度。

输入格式

第一行 2 个正整数 n,k。

接下来 n−1 行,每行 2 个正整数 u,v,表示第 u 座城市与第 v 座城市之间有一条长度为 1 的道路。

数据范围:

  • 1≤k<n≤105。
  • 1≤u,v≤n,u=v,保证城市与道路形成一棵树。

输出格式

一行一个整数,表示满足条件的最小交通拥堵度。

输入输出样例

输入 #1复制

复制代码
6 3
1 2
2 3
2 4
1 5
5 6

输出 #1复制

复制代码
1

说明/提示

【样例说明】

钦定 1,2,5 这 3 座城市为核心城市,这样 3,4,6 另外 3 座非核心城市与核心城市的距离均为 1,因此答案为 1。

实现代码:

cpp 复制代码
#include <bits/stdc++.h>

using namespace std;

struct edge {
	int t, nxt;
} e[200010];

struct qwqqwq {
	int a, b;
} qwqwqwq[100010];

bool cmp(qwqqwq a, qwqqwq b) {
	return a.a > b.a;
}

int head[100010], ep, dis[100010], father[100010], n, k, maxdis[100010], vis[100010], cnt, qqwq[100010];
// queue < int > q;

void add_edge(int s, int t) {
	ep++;
	e[ep].t = t;
	e[ep].nxt = head[s];
	head[s] = ep;
}

void dfs1(int now, int fa) {
	for(int i = head[now]; i; i = e[i].nxt) {
		if(e[i].t == fa) continue;
		dis[e[i].t] = dis[now] + 1;
		dfs1(e[i].t, now);
	}
}

void dfs2(int now, int fa) {
	for(int i = head[now]; i ; i = e[i].nxt) {
		if(e[i].t == fa) continue;
		father[e[i].t] = now;
		dis[e[i].t] = dis[now] + 1;
		dfs2(e[i].t, now);
	}
}

void dfs3(int now, int fa) {
	maxdis[now] = dis[now];
	for(int i = head[now]; i; i = e[i].nxt) {
		if(e[i].t == fa) continue;
		dis[e[i].t] = dis[now] + 1; 
		father[e[i].t] = now;
		dfs3(e[i].t, now);
		maxdis[now] = max(maxdis[now], maxdis[e[i].t]);
	} 
}

int main() {
	cin >> n >> k;
	for(int i = 1; i < n; i++) {
		int s, t;
		cin >> s >> t;
		add_edge(s, t);
		add_edge(t, s); 
	}
	dfs1(1, 0);
	int qwq = 0, pwp = 1;
	for(int i = 1; i <= n; i++) {
		if(dis[i] > qwq) {
			pwp = i, qwq = dis[i];
		}
	}
	memset(dis, 0, sizeof(dis));
	dfs2(pwp, 0);
	int qvq = 0; qwq = 1;
	for(int i = 1; i <= n; i++) {
		if(dis[i] > qvq) {
			qwq = i, qvq = dis[i];
		}
	}
	int pos1 = qwq;
	for(int i = 1; i <= (dis[qwq] + 1) / 2; i++) {
		pos1 = father[pos1];
	}
	memset(father, 0, sizeof(father));
	memset(dis, 0, sizeof(dis));
	dfs3(pos1, 0);
	// q.push(qwq);
	for(int i = 1; i <= n; i++) {
		qwqwqwq[i].a = maxdis[i] - dis[i];
		//cout << qwqwqwq[i].a << endl;
		qwqwqwq[i].b = i;
		qqwq[i] = qwqwqwq[i].a;
	}
	sort(qwqwqwq + 1, qwqwqwq + n + 1, cmp);
	for(int i = 1; i <= k; i++) {
		vis[qwqwqwq[i].b] = 1;
	}
	// cout << pos1 << endl;
	int ans = 0; 
	for(int i = 1; i <= n; i++) {
		if(!vis[i]) ans = max(qqwq[i] + 1, ans);
	}
	cout << ans << endl;
	return 0;
}

P5836 [USACO19DEC] Milk Visits S

题目描述

Farmer John 计划建造 N 个农场,用 N−1 条道路连接,构成一棵树(也就是说,所有农场之间都互相可以到达,并且没有环)。每个农场有一头奶牛,品种为更赛牛或荷斯坦牛之一。

Farmer John 的 M 个朋友经常前来拜访他。在朋友 i 拜访之时,Farmer John 会与他的朋友沿着从农场 Ai​ 到农场 Bi​ 之间的唯一路径行走(可能有 Ai​=Bi​)。除此之外,他们还可以品尝他们经过的路径上任意一头奶牛的牛奶。由于 Farmer John 的朋友们大多数也是农场主,他们对牛奶有着极强的偏好。他的有些朋友只喝更赛牛的牛奶,其余的只喝荷斯坦牛的牛奶。任何 Farmer John 的朋友只有在他们访问时能喝到他们偏好的牛奶才会高兴。

请求出每个朋友在拜访过后是否会高兴。

输入格式

输入的第一行包含两个整数 N 和 M。

第二行包含一个长为 N 的字符串。如果第 i 个农场中的奶牛是更赛牛,则字符串中第 i 个字符为 G,如果第 i 个农场中的奶牛是荷斯坦牛则为 H

以下 N−1 行,每行包含两个不同的整数 X 和 Y(1≤X,Y≤N),表示农场 X 与 Y 之间有一条道路。

以下 M 行,每行包含整数 Ai​,Bi​,以及一个字符 Ci​。Ai​ 和 Bi​ 表示朋友 i 拜访时行走的路径的端点,Ci​ 是 GH 之一,表示第 i 个朋友喜欢更赛牛的牛奶或是荷斯坦牛的牛奶。

输出格式

输出一个长为 M 的二进制字符串。如果第 i 个朋友会感到高兴,则字符串的第 i 个字符为 1,否则为 0

输入输出样例

输入 #1复制

复制代码
5 5
HHGHG
1 2
2 3
2 4
1 5
1 4 H
1 4 G
1 3 G
1 3 H
5 5 H

输出 #1复制

复制代码
10110

说明/提示

在这里,从农场 1 到农场 4 的路径包括农场 1、2 和 4。所有这些农场里都是荷斯坦牛,所以第一个朋友会感到满意,而第二个朋友不会。

关于部分分:

测试点 1 样例。

测试点 2∼5 满足 N≤103,M≤2⋅103。

对于 100% 的数据,1≤N≤105,1≤M≤105。

供题:Spencer Compton

实现代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
int fa[100010],ans[100010],M,N;
char col[100010];
int find(int x)
{
	if(x==fa[x])	return x;
	return fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
	fa[find(x)]=find(y);
}
int main()
{
	int cnt=0;
	cin>>N>>M;
	for(int i=1;i<=N;i++)
	{
		fa[i]=i;
		cin>>col[i];
	}	
	for(int i=1;i<=N-1;i++)
	{
		int u,v;cin>>u>>v;
		if(col[u]==col[v])	merge(u,v);
	}
	for(int i=1;i<=M;i++)
	{
		int a,b;	cin>>a>>b;
		char c;		cin>>c;
		if(find(a)==find(b)&&col[a]!=c)		ans[++cnt]=0;
		else	ans[++cnt]=1;
	}
	for(int i=1;i<=cnt;i++)	cout<<ans[i];
	return 0;
}
相关推荐
故事和你911 小时前
洛谷-【图论2-1】树1
开发语言·数据结构·c++·算法·深度优先·动态规划·图论
段ヤシ.1 小时前
回顾Java知识点,面试题汇总Day5(持续更新)
java·开发语言
不会C语言的男孩1 小时前
C++ SLTL编程
java·开发语言·c++
java修仙传1 小时前
Java 实习日记:从业务表关系到节点价格分析接口改造
java·开发语言·实习
qq_452396231 小时前
第十四篇:《JMeter插件扩展:自定义函数与第三方插件》
开发语言·python·jmeter
敲代码的嘎仔1 小时前
力扣高频SQL基础50题详解
开发语言·数据库·笔记·sql·算法·leetcode·后端开发
码农-阿杰1 小时前
Java 线程等待唤醒机制深度解析:synchronized、ReentrantLock、LockSupport 底层实现对比
java·开发语言·c++
赤水无泪1 小时前
Qt 全模块汇总列表
开发语言·qt
小虎牙0072 小时前
面试被问复杂度总懵?这篇指南帮你彻底搞清
算法