模擬賽 #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;
}