2020.07.24模拟5

luogu诚不欺我
果然——
今天大大爆炸
本打算着能T1T2能A掉
T4能QJ几个特判的测试点
结果最有把握的两个题
全部挂零儿
然后T4唯二的两个NO的点
完美的落在了我特判的YES上
于是本来就可怜巴巴的10分都没了

A.走廊泼水节

一句话题意

给个树n-1条边
让加边加成完全图
并且保证原树仍然是最小生成树

code

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch;
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

const int maxn = 6007;

struct node{
	int to, from, w;
	inline bool operator < (const node &x)const{
		return w < x.w;
	}
}edge[maxn << 1];
int fa[maxn], size[maxn];

inline int find(int x){
	if(fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}

int n;
inline void kruskal(){
	int ans = 0;
	sort(edge + 1, edge + n);
	for(int i = 1; i < n; i++){
		int x = edge[i].from;
		int y = edge[i].to;
		int w = edge[i].w;
		int xx = find(x);
		int yy = find(y);
		fa[xx] = yy;
		ans += (size[yy] * size[xx] - 1) * (w + 1);
		size[yy] += size[xx];
	}
	cout << ans << endl;
}

signed main(){
	int t = read();
	while(t--){
		memset(fa, 0, sizeof fa);
		memset(size, 0, sizeof size);
		n = read();
		for(int i = 1; i <= n; i++)
			fa[i] = i, size[i] = 1;
		for(int i = 1; i < n; i++){
			edge[i].from = read();
			edge[i].to = read();
			edge[i].w = read();
		}
		kruskal();
		/*
		for(int i = 1; i <= n ;i++)
			cout << size[i] << " ";
		cout << endl;
		*/
	}
	return 0;
}

B.Max Flow

题意

农场主约翰在他的N (2≤N≤50,000)个牛棚间安装了N-1条管道去运输牛奶,每个管道连接两个牛棚,每个牛棚都用管道直接或间接连接。
约翰在K(1≤K≤100,000)对牛棚间挤奶。假设约翰在第i对牛棚间挤奶,两牛棚分别是si,ti,这样挤出的牛奶将会经过si到ti间(包括端点)的每一个牛棚一次,在约翰挤完K对牛棚间的牛奶后,请问运输过牛奶次数最多的牛棚的运送次数是多少?

solution

树上差分裸题
板子挂了

code

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;

inline int read(){
	int x = 0, w = 1;
	char ch = getchar();
	for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') w = -1;
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
	return x * w;
}

const int maxn = 100010;

struct node{
	int to, nxt;
}edge[maxn << 1];
int head[maxn << 1], tot;

inline void add(int u, int v){
	edge[++tot].to = v;
	edge[tot].nxt = head[u];
	head[u] = tot;
}

int n, k;

int dep[maxn], fa[maxn][50];
inline void dfs(int u){
	dep[u] = dep[fa[u][0]] + 1;
	for(int i = 1; (1 << i) <= n; i++)
		fa[u][i] = fa[fa[u][i - 1]][i - 1];
	for(int i = head[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa[u][0]) continue;
		fa[v][0] = u;
		dfs(v);
	}
}

inline int lca(int u, int v){
	if(dep[u] < dep[v]) swap(u, v);
	int tmp = dep[u] - dep[v], k = 0;
	while(tmp){
		if(tmp & 1)
			u = fa[u][k];
		tmp >>= 1;
		k++;
	}
	if(u == v) return u;
	for(int i = 20; i >= 0; i--){
		if(fa[u][i] != fa[v][i]){
			u = fa[u][i];
			v = fa[v][i];
		}
	}
	return fa[u][0];
}

int a[maxn];
inline void solve(int u){
	for(int i = head[u]; i; i = edge[i].nxt){
		int v = edge[i].to;
		if(v == fa[u][0]) continue;
		solve(v);
		a[u] += a[v];
	}
}

int ans = 0;
signed main(){
	n = read(), k = read();
	for(int i = 1; i <= n - 1; i++){
		int u = read(), v = read();
		add(u, v);
		add(v, u);
	}
	dfs(1);
	for(int i = 1; i <= k; i++){
		int u = read(), v = read();
		a[u]++;
		a[v]++;
		a[lca(u, v)]--;
		a[fa[lca(u, v)][0]]--;
	}
	solve(1);
	for(int i = 1; i <= n; i++)	
		ans = max(ans, a[i]);
	cout << ans << '
';
	return 0;
}
原文地址:https://www.cnblogs.com/rui-4825/p/13374667.html