P4854 MloVtry的咸鱼树

推歌:Masquerade

传送

其实没什么难度,只要读懂题了就可以秒了。


题意:

给定 \(n\) 个点 \(m\) 条边的无向图 \(G\),每条边有一个权值 \(w\) 和点集 \(S\)

现在有一个点集 \(T\),初始只含有一个点。每次可以选择一条边 \((u,v,S,w)\),满足 \(u\in T\)\(v\in T\),且 \(S\subseteq T\)。可以花费 \(w\) 的代价令 \(T\to T\cup \{u,v\}\)

求令 \(T=\{1,2,\cdots,n\}\) 的最小花费。


看到 \(n\le 15\) 很容易想到状压,设 \(dp[T]\) 为当前点集为 \(T\) 的最小花费,每次转移暴力枚举边进行转移即可,实现是朴素的。

Code

#include <bits/stdc++.h>
using namespace std;
int n,m,dp[1<<15];
int u[380],v[380],T[380],w[380];
int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>u[i]>>v[i]>>T[i]>>w[i];
		u[i]--,v[i]--;
	}
	memset(dp,0x3f,sizeof(dp));
	dp[0]=0;
	for(int i=0;i<n;i++)dp[1<<i]=0;
	for(int S=0;S<(1<<n);S++)
		for(int i=1;i<=m;i++){
			if((S&T[i])!=T[i])continue;
			int x=1<<u[i],y=1<<v[i];
			if(S&(x|y))dp[S|x|y]=min(dp[S|x|y],dp[S]+w[i]);
		}
	if(dp[(1<<n)-1]==0x3f3f3f3f)cout<<"-1"<<endl;
	else cout<<dp[(1<<n)-1]<<endl;
	return 0;
}
posted @ 2025-11-09 11:17  Xuan_qwq  阅读(12)  评论(0)    收藏  举报