求助,非“超级源”做法40pts
查看原帖
求助,非“超级源”做法40pts
201971
william_zy楼主2022/6/25 10:45

求举反例或者反例情况

//思路:先在代价最少的地方凿井
//然后贪心找边,把边加到优先队列里面
//接着向外扩展农场,扩展了(n-1)个农场就结束了
#include<bits/stdc++.h>
using namespace std;
const int N=305;
int n;
int w[N];
int ans=0,vissum=0;
struct Edge1{//存图
	int end,w;
	Edge1(int end=0,int w=0):end(end),w(w){}
};
Edge1 g[N][N];
struct Edge{
	int u,v,w;
	Edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}
};
struct cmp{
	bool operator()(const Edge& a,const Edge& b){
		return a.w>b.w;
	}
};
bool vis[N];
void addedge(priority_queue<Edge,vector<Edge>,cmp>&,int);
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>w[i];
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++)
			cin>>g[i][j].w,g[i][j].end=j;
		sort(g[i]+1,g[i]+n+1,[](const Edge1& a,const Edge1& b){
			return a.w<b.w;//对每个点排序,按边长排序
		});
	}
	int x=1;
	for(int i=2;i<=n;i++){
		if(w[i]<w[x])x=i;//找最小w的起点
	}
	ans=w[x];
	vis[x]=1;
	vissum++;
	priority_queue<Edge,vector<Edge>,cmp> q;
	addedge(q,x);
	while(!q.empty()&&vissum<n){
		Edge tmp=q.top();
		q.pop();
		if(vis[tmp.u]){//tmp的端点u访问过了
			if(vis[tmp.v])continue;
			vis[tmp.v]=1;
			vissum++;
			ans+=min(tmp.w,w[tmp.v]);//tmp.v这个点扩展到了,可能是连到tmp.u上也可能是挖井了
			addedge(q,tmp.v);
		}else{//tmp的端点v访问过了
			vis[tmp.u]=1;
			vissum++;
			ans+=min(tmp.w,w[tmp.u]);//同理
			addedge(q,tmp.u);
		}
	}
	cout<<ans<<endl;
}
void addedge(priority_queue<Edge,vector<Edge>,cmp>& q,int x){//以点x为中心向外扩展边
	for(int i=1;i<=n;i++){
		if(i!=x){
			q.push(Edge(x,g[x][i].end,g[x][i].w));
		}
	}
}
2022/6/25 10:45
加载中...