PAT顶级 1001 Battle Over Cities

思路:

1.题意即求抹去哪个(些)点,剩下的点组成的最小生成树权值最小;
2.两点间没有公路权值设为无穷,公路未被破坏权值设为0(方便计算最小生成树权值);
3.需要注意一个城市被攻占后,剩余城市无法形成连通图的情况;(这时候代价设为无穷就行)

代码:

/*
	多希望和明理在一起的是贵树君你啊
	可惜在每秒下落五厘米的樱花中,你们错过了彼此 
*/
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define see(x) cerr<<x<<"--
";
#define fi first 
#define sc second
#define mp(a,b) make_pair(a,b)
using namespace std;
typedef pair<int,int> P;
const int maxv=505;
const int INF=1<<30;
int cost[maxv][maxv],mincost[maxv];
bool used[maxv];
int n,m,now;
void init_(){
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j)
	cost[i][j]=INF;
}
int prim(){
	for(int i=1;i<=n;++i) mincost[i]=INF,used[i]=false;
	int s=1,cnt=0,res=0; if(s==now) s++;
	mincost[s]=0;
	while(true){
		int v=-1;
		for(int u=1;u<=n;++u){
			if(!used[u]&&u!=now&&mincost[u]!=INF&&(v==-1||mincost[u]<mincost[v])) v=u;
		}
		if(v==-1) break;
		used[v]=true; cnt++;
		res+=mincost[v];
		for(int u=1;u<=n;++u) mincost[u]=min(mincost[u],cost[v][u]);
	}
	return cnt==n-1?res:INF;
}
bool cmp(const P& a,const P& b){return a.fi==b.fi?a.sc<b.sc:a.fi>b.fi;}
void solve(){
	vector<P> v(n);
	for(now=1;now<=n;++now) v[now-1]=mp(prim(),now);
	sort(v.begin(),v.end(),cmp);
	if(v[0].fi==0) cout<<0;
	else{
		cout<<v[0].sc;
		for(int i=1;i<n;i++){
			if(v[i].fi==v[i-1].fi) cout<<' '<<v[i].sc;
			else break;
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
   //	freopen("Sakura.txt","r",stdin);
	cin>>n>>m;
	init_();
	while(m--){
		int a,b,c,s; cin>>a>>b>>c>>s;
		if(s==0) cost[a][b]=cost[b][a]=c;
		else cost[a][b]=cost[b][a]=0;
	}
	solve();
	return 0;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308743.html