蒟蒻疑惑这道题直接贪心求最小生成树为社么是错的(
查看原帖
蒟蒻疑惑这道题直接贪心求最小生成树为社么是错的(
762019
yushanxuanfeng楼主2023/11/10 17:28

枚举以每个点为根节点的情况,每次枚举所有与已经开凿出的宝藏屋链接的道路,边权为 w∗(dis[u]+1)w*(dis[u]+1) 然后最小生成树求解

这么做为什么只能得到 vv 相等的部分分啊,不知道思路错在哪了(悲)谢谢各位大佬(

屎山代码

#include<bits/stdc++.h>
#define N 20
using namespace std;
int n,m,cnt,f[N],dis[N],e[N][N];
int ans=91919810;
int find(int x){ return f[x]==x?x:f[x]=find(f[x]); }
struct edge{
	int u,v,w;
	bool operator<(const edge &x)const{return w>x.w;}
};
priority_queue<edge>q;
void solve(int root){
	int res=0,idx=0;
	while(!q.empty()) q.pop();
	for(int i=1;i<=n;i++) f[i]=i,dis[i]=0;
	for(int _=1;_<n;_++){
		for(int u=1;u<=n;u++){
			if(u!=root&&!dis[u]) continue;//如果当前点不能达到就跳过 
			for(int v=1;v<=n;v++){
				if(v==u||!e[u][v]) continue;
				q.push((edge){u,v,(dis[u]+1)*e[u][v]});
			}
		}
		while(!q.empty()){
			edge temp=q.top();
			q.pop();
			int u=temp.u,v=temp.v,w=temp.w;
			int uu=find(u),vv=find(v);
			if(uu==vv) continue;
			f[uu]=vv,res+=w,dis[v]=dis[u]+1;
			idx++;
			break;
		}
	}
	if(idx==n-1) ans=min(ans,res);//如果正好加了n-1条边就更新答案 
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	for(int u=1;u<=n;u++){
		for(int v=1;v<=n;v++){
			e[u][v]=91919810;
		}
	}
	for(int i=1,u,v,w;i<=m;i++){
		cin>>u>>v>>w;
		e[u][v]=e[v][u]=min(e[u][v],w);
	}
	for(int i=1;i<=n;i++) solve(i);//以i为根的树 
	cout<<ans<<endl;
}
2023/11/10 17:28
加载中...