这个题的题意是假设某个城市被占领后,要使剩下的城市保持联通可能会花钱修路,求最小花费里花费最多的那个被占领的城市。
这个题凭感觉就是最小生成树,最小生成树满足权值最小(最小花费),所以依次去掉某个城市的所有与其相接的路径,把剩下的路加入最小生成树,求最大值即可。
有一个地方写的时候没注意到,就是去掉某个城市后可能导致连通块的数量的增多,这种情况下算这个城市的花费无限大就可以了(自己真菜QAQ)。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> #include <vector> #include <cmath> using namespace std; const int INF = 0x3f3f3f3f; int n,m,max1; int f[505]; vector<int> ans; struct P{ int u,v,c,s; bool operator<(const P &a)const{ if(s != a.s) return s > a.s;//优先选择还能用的路,这种路径不增加花费 else return c<a.c;//其实是处理需要修理的路径,先修花费少的 } }p[250005]; int Find(int x){ if(x==f[x]) return x; else return f[x]=Find(f[x]); } int main(){ scanf("%d%d",&n,&m); max1=0; for(int i=1;i<=m;i++) scanf("%d%d%d%d",&p[i].u,&p[i].v,&p[i].c,&p[i].s); sort(p+1,p+1+m); for(int i=1;i<=n;i++){ int num=0,cnt=0; for(int i=1;i<=n;i++) f[i]=i; for(int j=1;j<=m;j++){ if(num==n-2) break; int u=p[j].u; int v=p[j].v; if(u==i || v==i) continue ;//去掉某个城市 u=Find(u); v=Find(v); if(u!=v){ f[u]=v; num++; if(p[j].s==0) cnt+=p[j].c; } } if(num!=n-2){//先判断删除某个城市后是否连通 if(max1!=INF){ max1=INF; ans.clear(); } ans.push_back(i); }else{ if(cnt>max1){ max1=cnt; ans.clear(); ans.push_back(i); }else if(cnt==max1 && max1!=0) ans.push_back(i); } } if(ans.size()==0) printf("0\n"); else{ sort(ans.begin(),ans.end()); printf("%d",ans[0]); for(int i=1;i<ans.size();i++) printf(" %d",ans[i]); } return 0; }
原文地址:https://www.cnblogs.com/JustDoA/p/11180592.html
时间: 2024-10-05 03:09:53