首页 > 其他分享 >USACO2018(铂金组)

USACO2018(铂金组)

时间:2023-10-24 22:14:15浏览次数:34  
标签:ch int 边权 USACO2018 fa maxn 铂金 define

前言:

教练给我们做铂金组的题目真的抬举我们了……

[USACO18OPEN] Disruption P

题目描述:

你有一棵节点数为 \(n\),边数为 \(n-1\) 的树。然后你会给这棵树新增加 \(m\) 条边,对于每条边,有 \(u,v,w\) 分别表示边连接的两个节点分别为 \(u\) 和 \(v\),和一个边权 \(w\)。每次删掉一条原树边,然后如果要使原图依旧联通,则需要添加的额外边的边权最小为多少。

数据范围:

\(1\leq N\leq 5\times 10^4,1\leq M\leq 5\times 10^4\)

思路:

我们发现,如果去枚举到底删掉的是那一条边,则去计算最小加的边的边权是不太方便处理的。那我们不如换一种思路:对于每一条边,他能对那些边造成贡献。如图:
image

我们如果添加了一条边权为 \(a\) 的边,则可能造成贡献的边就应该为蓝色的路径所覆盖的边。因此问题转换为求区间最值的问题。显然可以用树剖+线段树维护。

但是,我们依旧认为这个方法过于的无脑,没有思维含量 其实是我不会

显然的,我们可以将所有的非树边全部按照边权排序,显然的,每次遍历到的最小的边所能造成影响的路径中的边全都应为这个非树边的边权。证明也是比较显然的。
对于这样的一个操作,我们可以使用并查集来维护。

点击查看代码
#include<bits/stdc++.h>
#define int long long
#define mem(a) memset(a,0,sizeof(a))
#define set(a,b) memset(a,b,sizeof(a))
#define ls p<<1
#define rs p<<1|1
#define pb(x) push_back(x)
#define pt(x) putchar(x)
#define T int t;cin>>t;while(t--)
#define rand RAND
#define LOCAL
using namespace std;
char buf[1<<20],*p1,*p2;
#define gc()(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
template<class Typ> Typ &re(Typ &x){char ch=gc(),sgn=0; x=0;for(;ch<'0'||ch>'9';ch=gc()) sgn|=ch=='-';for(;ch>='0'&&ch<='9';ch=gc()) x=x*10+(ch^48);return sgn&&(x=-x),x;}
template<class Typ> void wt(Typ x){if(x<0) putchar('-'),x=-x;if(x>9) wt(x/10);putchar(x%10^48);}
const int inf=0x3f3f3f3f3f;
const int maxn=50005;
const int mod=1e9+7;
int seed = 19243;
unsigned rand(){return seed=(seed*48271ll)%2147483647;}
void file(string s){freopen((s+".in").c_str(),"r",stdin);freopen((s+".out").c_str(),"w",stdout);return;}
int n,m;
vector<pair<int,int>>G[maxn];
struct Ds{
	int fa[maxn];
	int find(int x){
		if(x!=fa[x])return fa[x]=find(fa[x]);
		return fa[x];
	}
}ds;
int fa[maxn][20];
int g[maxn],Id[maxn],dep[maxn];
void dfs(int u,int f){
	dep[u]=dep[f]+1;
	fa[u][0]=f;
	g[u]=f;
	for(auto k:G[u]){
		int v=k.first,id=k.second;
		if(v==f)continue;
		Id[v]=id;
		dfs(v,u);
	}
}
int ans[maxn];
struct node{
	int u,v,w;
	bool operator<(const node&x)const{
		return w<x.w;
	}
}E[maxn];
signed main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)ds.fa[i]=i;
	for(int i=1;i<n;i++){
		int u,v;cin>>u>>v;
		G[u].push_back({v,i});
		G[v].push_back({u,i});
	}
	dfs(1,0);
	for(int j=1;j<=18;j++){
		for(int i=1;i<=n;i++)
			fa[i][j]=fa[fa[i][j-1]][j-1];
	}
	for(int i=1;i<=m;i++){
		cin>>E[i].u>>E[i].v>>E[i].w;
	}
	sort(E+1,E+m+1);
	memset(ans,-1,sizeof(ans));
	for(int i=1;i<=m;i++){
		for(int a=ds.find(E[i].u),b=ds.find(E[i].v);a!=b;){
			if(dep[a]<dep[b])swap(a,b);
			ds.fa[a]=ds.fa[g[a]];
			ans[Id[a]]=E[i].w;
			a=ds.find(a),b=ds.find(b);
		}
	}
	for(int i=1;i<n;i++)cout<<ans[i]<<endl;
	return 0;
}

标签:ch,int,边权,USACO2018,fa,maxn,铂金,define
From: https://www.cnblogs.com/Candycar/p/17785825.html

相关文章

  • [usaco2018 jan] sprinklers
    题目农夫约翰有一块很大的田,他正在考虑种甜玉米。经过对他农田的调查,FJ发现它形成了一个(N-1)×(N-1)的正方形。西南角为坐标(0,0),东北角是(N-1,N-1)。在某些整数坐标的位置中有双头喷头,每一个都能够同时喷洒水和肥料。一个在(i,j)处的双头喷头会将水洒在农田中所有在其东面且在其北面的区......
  • Oracle最高可用性架构(MAA)|铂金级(PLATINUM)
    1、什么是MAAMAA即最高可用性架构(MaximumAvailabilityArchitecture )Oracle最高可用性架构(MAA)为Oracle数据库提供了架构、配置和生命周期最佳实践参考之前的文章:1、Oracle最高可用性架构(MAA)|青铜级(BRONZE)https://www.cnblogs.com/mingfan/p/16804556.html2、Oracle最......
  • 文明6铂金版 mac(策略游戏) v1.3.13中文激活版
    文明6是人气颇高的《文明》系列中的经典作品,共有20位史上著名的领袖任君挑选,包括秦始皇。全新扩展包中,科技与市政树已扩展至未来时代,玩家们可在8个新文明与9位新领袖中进行......
  • USACO 2022 Dec 铂金组题解
    有生之年终于AK一次Pt组了,发个题解玩玩。T1-Breakdown大部分情况下,题目里若存在一个很小的\(k\)这样的角色,都是因为它在复杂度指数上(包括但不限于\(2^{\operato......