2024 SDSC 提高班

CheZiHe929發表於2024-09-01

模擬賽 #1

T1-risk

類原題:P3366 【模板】最小生成樹

題意:給定 \(n\) 個點 \(m\) 條邊的帶權無向圖,每個點上都有一定數量的軍隊,合併兩個相鄰點的軍隊的代價為邊權 \(w\),求將所有的軍隊合併的最小代價。

不難發現最後的集結過程一定是一棵樹,所以最小代價為此圖的最小生成樹的大小。

點選檢視程式碼
int to[MAXN];
int go(int p){return (to[p]==p?p:to[p]=go(to[p]));} 

struct edge{
	int s,e,d;
}ed[MAXN];
 
int n,m;

bool cmp(edge a,edge b){
	return a.d<b.d;
}

signed main(){
	n=read(),m=read();
	for(int i=1;i<=m;i++)
		ed[i].s=read(),ed[i].e=read(),ed[i].d=read();
		
	std::sort(ed+1,ed+m+1,cmp);
	
	for(int i=1;i<=n;i++)
		to[i]=i;
		
	int ans=0;
	int cnt=0;
	for(int i=1;i<=m;i++){//最小生成樹 
		if(cnt==n-1)break;
		int p1=ed[i].s,p2=ed[i].e,d=ed[i].d;
		if(go(p1)!=go(p2)){
			ans+=d;
			to[go(p1)]=go(p2);
			++cnt;
		}
	}

	println(ans);
	return 0;
}

T2-magic

原題:CF1346E Magic Tricks

首先考慮樸素的 DP,設 \(dp_{i,j}\) 表示在第 \(i\) 次操作後,關鍵球在 \(j\) 的最小花費。不難得到轉移,\(dp_{i,x_i}=\min(dp_{i-1,x_i}+1,dp_{i-1,y_i}),dp_{i,y_i}=\min(dp_{i-1,y_i}+1,dp_{i-1,x_i})\)

發現每次轉移第一維沒有貢獻,可以用滾動陣列將第一維滾掉。

點選檢視程式碼
int n,m,k,x,y,dp[MAXN];
signed main(){	
	n=read(),m=read(),k=read();
	
	memset(dp,0x3f,sizeof(dp));
	dp[k]=0;//dp 初始化 
	
	for(int i=1;i<=m;i++){
		x=read(),y=read();
		int nowx=dp[x],nowy=dp[y];//注意:先存下 dp[x],dp[y] 的值 
		dp[x]=std::min(nowx+1,nowy);
		dp[y]=std::min(nowx,nowy+1);//dp 的轉移 
	}
		
	for(int i=1;i<=n;i++)
		put((dp[i]>m?-1:dp[i]),i,n);
	
	return 0;
}