标签:for vector iostream src opened target alt close size
题意:
无向图,给n个城市,n*n条边,每条边都有一个权值 代表修路的代价,其中有k个点有发电站,给出这k个点的编号,要每一个城市都连到发电站,问最小的修路代价。
思路:
prim:把发电站之间e[i][j]都设置为0,然后模板套进去就行。
krusl:把所有的发电站都先弄进一个并查集(做法比较机智,先拿其中一个发电站,把剩下的发电站分别与这个发电站找父节点,分别弄进并查集就行)。 然后按权值从小到大 排序,不是同一个并查集的就sum+=,再弄进并查集。
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=2e5+5; int n,m; int e[105][105]; int b[105],dis[105],vis[105]; void prim() { for(int i=1;i<=n;i++) { vis[i]=0; dis[i]=e[1][i]; } int u,minn,sum=0; vis[1]=1; for(int i=1;i<n;i++) { minn=INF; for(int j=1;j<=n;j++) { if(!vis[j] && minn>dis[j]) { u=j; minn=dis[j]; } } vis[u]=1; sum+=minn; for(int j=1;j<=n;j++) { if(!vis[j] && e[u][j]<dis[j]) dis[j]=e[u][j]; } } printf("%d\n",sum); } int main() { cin>>n>>m; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i==j) e[i][j]=0; else e[i][j]=INF; for(int i=1;i<=m;i++) scanf("%d",&b[i]); for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ scanf("%d",&e[i][j]); } } for(int i=1;i<=m;i++) for(int j=1;j<=m;j++) e[b[i]][b[j]]=0; prim(); }
#include<iostream> #include<cstdio> #include <cctype> #include<algorithm> #include<cstring> #include<cmath> #include<string> #include<cmath> #include<set> #include<vector> #include<stack> #include<queue> #include<map> using namespace std; #define ll long long #define mem(a,x) memset(a,x,sizeof(a)) #define se second #define fi first const ll mod=998244353; const int INF= 0x3f3f3f3f; const int N=2e5+5; int f[N],n,m; struct edge { int u,v,w; }e[N]; bool cmp(edge x,edge y) { return x.w<y.w; } int getf(int x) { if(x!=f[x]) f[x]=getf(f[x]); return f[x]; } int krusl(int num) { int fa,fb,sum=0,cnt=0; for(int i=1;i<=num;i++) { fa=getf(e[i].u); fb=getf(e[i].v); if(fa!=fb) { f[fa]=fb; sum+=e[i].w; cnt++; } if(cnt==n-m) break; } return sum; } int main() { cin>>n>>m; for(int i=0;i<=n;i++) f[i]=i; int q; cin>>q; //拿q与其他所有的发电站都连接起来 for(int i=2;i<=m;i++) { int fa,fb,a; cin>>a; fa=getf(a); fb=getf(q); if(fa!=fb) f[fa]=fb; } int cnt=0; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { e[++cnt].u=i; e[cnt].v=j; scanf("%d",&e[cnt].w); } } sort(e+1,e+1+cnt,cmp); cout<<krusl(cnt)<<endl; }
Electrification Plan 最小生成树(prim+krusl)
标签:for vector iostream src opened target alt close size
原文地址:https://www.cnblogs.com/thunder-110/p/10329445.html