難存的情緣&貨車運輸

shaoyufei發表於2024-05-22

事先說明,參考的oceans_of_stars,順便%一下(有事他背鍋

一個求最大,一個求最小,沒啥好說的,拿難存的情緣舉例說明邊權如何轉點權


一天機房的夜晚,無數人在MC裡奮鬥著。。。
大家都知道礦產對於MC來說是多麼的重要,但由於礦越挖越少,勇士們不得不跑到更遠的地方挖礦,但這樣路途上就會花費相當大的時間,導致挖礦效率低下。
cjj提議修一條鐵路,大家一致同意。
大家都被CH分配了一些任務:
zjmfrank2012負責繪製出一個礦道地圖,這個地圖包括家(當然這也是一個礦,畢竟不把家掏空我們是不會走的),和無數個礦,所以大家應該可以想出這是一個無向無環圖,也就是一棵樹。
Digital_T和cstdio負責鋪鐵路。。所以這裡沒他們什麼事,兩位可以勞作去了。
這個時候song526210932和RMB突然發現有的礦道會刷怪,並且怪的數量會發生變化。作為採礦主力,他們想知道從一個礦到另一個礦的路上哪一段會最困難。。。(困難值用zjm的死亡次數表示)。

輸入格式
輸入檔案的第一行有一個整數N,代表礦的數量。礦的編號是1到N。

接下來N-1行每行有三個整數a,b,c,代表第i號礦和第j號礦之間有一條路,在初始時這條路的困難值為c。

接下來有若干行,每行是“CHANGE i ti”或者“QUERY a b”,前者代表把第i條路(路按所給順序從1到M編號)的困難值修改為ti,後者代表查詢a到b所經過的道路中的最大困難值。

輸入資料以一行“DONE”結束。

輸出格式
對每個“QUERY”操作,輸出一行一個正整數,即最大困難值。

樣例
樣例輸入
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
樣例輸出
1
3
資料範圍與提示
對於60%的資料,1<=N<=50

對於100%的資料,1<=N<=10000,1<=c<=1000000,1<=操作次數<=100000

最主要的問題是,如何把邊權轉點權,以及如何去將修改邊轉化為修改點
有一個方法就是將邊權賦給兒子(邊兩端中深度較大的那個點)
image
image

對應程式碼
void dfs1(int now){
	son[now]=-1;
	siz[now]=1;
	for(int i=head[now];i;i=edge[i].from){
		int to=edge[i].to;
		if(dep[to]) continue;
		a[to]=edge[i].w;//這裡
		dep[to]=dep[now]+1;
		fa[to]=now;
		dfs1(to);
		siz[now]+=siz[to];
		if(son[now]==-1||siz[to]>siz[son[now]]) son[now]=to;
	}
}

但這樣就有兩個問題
1.按樹剖求路徑最大會多算

image
我的本意是想要求4,3與3,3的邊的最大值,但實際上還與1,3這條邊進行了比較,這會導致誤差
所以我們要去掉這個點,實際上也很好像想(不好想)因為這個點的下標一定是兩個點跳到同一重鏈後那個深度淺的點的dfn值,只需要給它+1,就可以解決了
2.對應點,我們存一下每個邊的編號,然後修改的的點一定是對應邊中深度深的那個點,也可以在一開始的編號中記錄一下,都是一樣的

第一種
	cnt1++;
	add(from,to,w);
	add(to,from,w);
	line[cnt1].from=from;
	line[cnt1].to=to;
	line[cnt1].w=w;
	//記錄邊的編號
cin>>from>>to;
int dian=0;		
if(dep[line[from].from]>dep[line[from].to]){
	dian=line[from].from;
}
else dian=line[from].to;
update(1,dfn[dian],to);
//找深度深的點
第二種
void dfs1(int now){
	son[now]=-1;
	siz[now]=1;
	for(int i=head[now];i;i=edge[i].from){
		int to=edge[i].to;
		if(dep[to]) continue;
		a[to]=edge[i].w;
		dian[edge[i].id]=to;//這裡
		dep[to]=dep[now]+1;
		fa[to]=now;
		dfs1(to);
		siz[now]+=siz[to];
		if(son[now]==-1||siz[to]>siz[son[now]]) son[now]=to;
	}
}

然後就沒了

點選檢視程式碼
#include<bits/stdc++.h>
using namespace std;
#define lson id<<1
#define rson id<<1|1
const int N=1e6+1000;
typedef long long ll;
int n,m,head[N];
int top[N],dfn[N],siz[N],son[N],fa[N];
int a[N],cnt,num,dep[N],b[N];
struct node{
	int l,r,max;
}tr[N<<2];
struct node1{
	int from;
	int to;
	int w;
}edge[N<<2],line[N];
void add(int from,int to,int w){
	cnt++;
	edge[cnt].from=head[from];
	edge[cnt].to=to;
	edge[cnt].w=w;
	head[from]=cnt;
}
void dfs1(int now){
	son[now]=-1;
	siz[now]=1;
	for(int i=head[now];i;i=edge[i].from){
		int to=edge[i].to;
		if(dep[to]) continue;
		a[to]=edge[i].w;
		dep[to]=dep[now]+1;
		fa[to]=now;
		dfs1(to);
		siz[now]+=siz[to];
		if(son[now]==-1||siz[to]>siz[son[now]]) son[now]=to;
	}
}
void dfs2(int now,int tp){
	top[now]=tp;
	num++;
	b[num]=a[now];
	dfn[now]=num;
	if(son[now]==-1) return;
	dfs2(son[now],tp);
	for(int i=head[now];i;i=edge[i].from){
		int to=edge[i].to;
		if(to!=fa[now]&&to!=son[now]) dfs2(to,to);
	}
}
void build(int id,int l,int r){
	tr[id].l=l;
	tr[id].r=r;
	if(l==r){
		tr[id].max=b[l];
		return;
	}
	int mid=(l+r)/2;
	build(lson,l,mid);
	build(rson,mid+1,r);
	tr[id].max=max(tr[lson].max,tr[rson].max);
}
void update(int id,int x,int ad){
	if(tr[id].l==tr[id].r){
		tr[id].max=ad;
		return;
	}
	int mid=(tr[id].l+tr[id].r)/2;
	if(x<=mid) update(lson,x,ad);
	else update(rson,x,ad);
	tr[id].max=max(tr[lson].max,tr[rson].max); 
}
int getmax(int id,int l,int r){
	if(l>tr[id].r||r<tr[id].l) return -0x7fffffff;
	if(l<=tr[id].l&&tr[id].r<=r){
		return tr[id].max;
	}
	return max(getmax(lson,l,r),getmax(rson,l,r));
}
int treemax(int x,int y){
	int maxn=-0x7fffffff;
	while(top[x]!=top[y]){
		if(dep[top[x]]<dep[top[y]]) swap(x,y);
		maxn=max(maxn,getmax(1,dfn[top[x]],dfn[x]));
		x=fa[top[x]];
	}
	if(dep[x]>dep[y]) swap(x,y);
	maxn=max(maxn,getmax(1,dfn[x]+1,dfn[y]));
	return maxn;
}
int main(){
	string str;
	int cnt1=0;
	int c,from,to,w;
	cin>>n;
	for(int i=1;i<n;i++){
		cin>>from>>to>>w;
		cnt1++;
		add(from,to,w);
		add(to,from,w);
		line[cnt1].from=from;
		line[cnt1].to=to;
		line[cnt1].w=w;
	}
	dep[1]=1;
	dfs1(1);
	dfs2(1,1);
	build(1,1,n);
	while(cin>>str&&str!="DONE"){
		if(str=="QUERY"){
			cin>>from>>to;
			cout<<treemax(from,to)<<endl;
			
		}
		else {
			cin>>from>>to;
			int dian=0;
			if(dep[line[from].from]>dep[line[from].to]){
				dian=line[from].from;
			}
			else dian=line[from].to;
			update(1,dfn[dian],to);
		}
	}
}

相關文章