文章目录
最小生成树
题目1: P3366 【模板】最小生成树
prim 求最小生成树O(n^2) 朴素版
#include<bits/stdc++.h>
using namespace std;
const int N = 5010;
const int INF = 0x3f3f3f3f;
int n ,m;
int g[N][N];
int dist[N];
bool st[N];
int prim()
{
memset(dist,0x3f,sizeof dist);
dist[1] = 0;
int res = 0;
for(int i = 0;i<n;i++)
{
int t = -1;
for(int j = 1;j<=n;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]))
t = j;
}
if(i&&dist[t]==INF) return INF;
if(i) res+=dist[t];
st[t] = true;
for(int j = 1;j<=n;j++) dist[j] = min(dist[j],g[t][j]);
}
return res;
}
int main()
{
memset(g,0x3f3f3f3f,sizeof g);
cin>>n>>m;
while(m--)
{
int a,b,c;
cin>>a>>b>>c;
g[a][b] = g[b][a] = min(g[a][b],c);
}
int t = prim();
if(t==INF) puts("orz");
else cout<<t;
return 0;
}
kruskal求最小生成树 O(mlogm)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m;
const int N = 1e5+10;
int p[N];
int find(int x)
{
if(p[x]!=x) p[x] = find(p[x]);
return p[x];
}
struct Edge{
int a,b,w;
bool operator<(const Edge &W) const
{
return w<W.w;
}
}edges[2*N];
int main()
{
cin>>n>>m;
for(int i = 0;i<m;i++)
{
int a,b,w;
cin>>a>>b>>w;
edges[i] = {a,b,w};
}
sort(edges,edges+m);
for(int i = 1;i<=n;i++) p[i] = i;
int res = 0,cnt = 0;
for(int i= 0;i<m;i++)
{
int a = edges[i].a, b= edges[i].b,w = edges[i].w;
a = find(a),b = find(b);
if(a!=b)
{
p[a] = b;
res+=w;
cnt++;
}
}
if(cnt<n-1) puts("orz");
else cout<<res;
return 0;
}
题目2: P1546 [USACO3.1]最短网络 Agri-Net
#include<bits/stdc++.h>
using namespace std;
const int N = 210;
const int INF = 0x3f3f3f3f;
int n,m;
int g[N][N];
int dist[N];
bool st[N];
//O(n^2)
int prim()
{
memset(dist,0x3f,sizeof dist);
//先初始化dist数组
int res = 0;
dist[1] = 0;
for(int i = 0;i<n;i++)
{
int t = -1;
for(int j = 1;j<=n;j++)
{
if(!st[j]&&(t==-1||dist[t]>dist[j]))
{
t = j;
}
}
res+=dist[t];//如果i==0说明只有一个点,不可能有边
st[t] = true;
for(int j = 1;j<=n;j++)
dist[j] = min(dist[j],g[t][j]);
}
return res;
}
int main()
{
memset(g,0x3f3f3f3f,sizeof g);
cin>>n;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=n;j++)
cin>>g[i][j];
}
int t = prim();
cout<<t;
return 0;
}
题目3:P2820 局域网
kruskal模板题
/*
1.将所有边按权重从小到大排序 O(mlogm)
2.枚举每一条边a->b 权重为c
if(!st[a][b]) 将a,b加入集合中
*/
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 100010;
int n,m;
int p[N];
struct Edge
{
int a,b,w;
bool operator<(const Edge &W) const
{
return w<W.w;
}
}edges[2*N];
int find(int x)
{
if(p[x]!=x) p[x] = find(p[x]);
return p[x];
}
int main()
{
cin>>n>>m;
int sum = 0;
for(int i = 0;i<m;i++)
{
int a,b,w;
cin>>a>>b>>w;
sum+=w;
edges[i] = {a,b,w};
}
sort(edges,edges+m);
for(int i = 1;i<=n;i++) p[i] = i;
int res = 0,cnt = 0;
for(int i= 0;i<m;i++)
{
int a = edges[i].a, b= edges[i].b,w = edges[i].w;
a = find(a),b = find(b);
if(a!=b)
{
p[a] = b;
res+=w;
cnt++;
}
}
cout<<sum-res;
return 0;
}
题目4:P2330 [SCOI2005]繁忙的都市
挺有意思的一个题,需要注意先把编号p为1的数据预处理了过后,再去处理p=2的数据,不然可能会多计数…kruskal解决~
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int N = 310,M = 8010;
struct edge{
int a,b,w;
bool operator< (const edge &W)const{
return w<W.w;
}
}edges[M];
int p[N];
int find(int x)
{
if(x!=p[x]) return p[x] = find(p[x]);
return x;
}
int main()
{
cin>>n>>m;
for(int i = 0;i<m;i++)
{
cin>>edges[i].a>>edges[i].b>>edges[i].w;
}
sort(edges,edges+m);
for(int i = 1;i<=n;i++)
p[i] = i;
int res = 0,cnt = 0;
for(int i = 0;i<m;i++)
{
int a = edges[i].a,b = edges[i].b,w = edges[i].w;
int pa = find(a),pb = find(b);
if(pa!=pb)
{
p[pa] = pb;
res = max(res,w);
cnt++;
}
}
cout<<cnt<<" "<<res;
}