思路:
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;
}