1.prim 类似于dijkstra 松弛就好 题目 51nod基础题 无向图最短生成树
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <sstream>
#include <ostream>
#include <algorithm>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <vector>
#define inf 1e9+7
#define pi acos(-1)
#define natrule exp(1)
using namespace std;
int g[1005][1005];
int d[1005];
bool used[1005];
long long prim(int n,int m)
{
long long ans=0;
d[1]=0;
int now;
while(true)
{
int mark=1;
int maxx=inf;
for(int i=1;i<=n;i++)
{
if(!used[i]&&d[i]<maxx) {
maxx=d[i];
now=i;
mark=0;
}
}
used[now]=true;
for(int i=1;i<=n;i++)
{
if(!used[i]&&d[i]>g[now][i])
{
d[i]=g[now][i];
}
}
if(mark) break;
}
for(int i=1;i<=n;i++) ans+=d[i];
return ans;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<1005;i++)
{
for(int j=0;j<1005;j++)
g[i][j]=inf;
}
for(int i=0;i<1005;i++) d[i]=inf;
for(int i=0;i<m;i++)
{
int s,e,value;
cin>>s>>e>>value;
g[s][e]=g[e][s]=value;
}
cout<<prim(n,m)<<endl;
return 0;
}
堆优化
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <sstream>
#include <ostream>
#include <algorithm>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <vector>
#define inf 1e9+7
#define pi acos(-1)
#define natrule exp(1)
using namespace std;
struct edge{
int to,cost;
};//临街表+G
typedef pair<int,int> P;//first 储存最短距离 second 储存的是编号 因为greater 默认为first升序排列
vector<edge> G[1005];
int used[1005];
int d[1005];
long long prim(int n,int m)
{
priority_queue<P,vector<P>,greater<P> > qq;
d[1]=0;
qq.push(make_pair(0,1));
long long ans=0;
int cnt=1;
while(!qq.empty())
{
// cout<<cnt++<<endl;
P a=qq.top();
qq.pop();
if(used[a.second]) continue;
used[a.second]=1;
ans+=a.first;
for(int i=0;i<G[a.second].size();i++)
{
edge eg=G[a.second][i];
if(!used[eg.to]&&d[eg.to]>eg.cost)
{
d[eg.to]=eg.cost;
P now;
now.first=d[eg.to];
now.second=eg.to;
qq.push(now);
}
}
}
return ans;
}
int main(){
int m,n;
cin>>n>>m;
for(int i=0;i<m;i++)
{
int s,e,value;
cin>>s>>e>>value;
edge k;
k.to=e;
k.cost=value;
G[s].push_back(k);
k.to=s;
G[e].push_back(k);
}
for(int i=0;i<1005;i++) d[i]=inf;
cout<<prim(n,m);
return 0;
}
堆优化的时候由于图不是稀疏图 所以在小规模下优化也不是很明显 第一个跑了158ms 堆优化竟然有140ms
总结 :发现和dij惊人的相似 只不过松弛的时候不是到源点的距离的最小值 而是到没有访问过的点的最小边长,同样用堆优化 used判断一下是否访问过即可。
2.kruskal 算法 高效的并查集操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include <sstream>
#include <ostream>
#include <algorithm>
#include <ctype.h>
#include <cmath>
#include <queue>
#include <vector>
#define inf 1e9+7
#define pi acos(-1)
#define natrule exp(1)
using namespace std;
int fa[1005];
int height[1005];
void init_union(int n)
{
for(int i=0;i<n;i++)
{
fa[i]=i;
height[i]=0;
}
}
int find(int x)
{
if(fa[x]==x) return x;
else return fa[x]=find(fa[x]);
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return ;
if(height[x]<height[y])
fa[x]=y;
else
{
fa[y]=x;
if(height[y]==height[x]) ++height[x];
}
}
bool same(int x,int y)
{
return find(x)==find(y);
}
struct edge{
int s,e,w;
};
bool cmp(const edge& e1,const edge &e2)
{
return e1.w<e2.w;
}
edge eg[50005];
int kruskal(int n,int m){
sort(eg,eg+m,cmp);
init_union(n);
int res=0;
for(int i=0;i<m;i++)
{
edge e=eg[i];
if(!same(e.s,e.e)){
unite(e.s,e.e);
res+=e.w;
}
}
return res;
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=0;i<m;i++)
{
int s,e,value;
cin>>s>>e>>value;
eg[i].s=s;
eg[i].e=e;
eg[i].w=value;
}
cout<<kruskal(n,m);
return 0;
}