Prim算法过程:
dist[i] 初始化正无穷
迭代n次 :
找到距离集合最近的点 t ;用t更新其他点距离集合的距离;将t加入到集合中 st[t] = true;
//适合稠密图
int prim()
{
int res =0;
memset(dist,0x3f,sizeof dist);
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) reuturn INF;
if(i) res+=dist[t];
for(int j=1;j<=n;j++)
dist[j]=min(dist[j],g[t][j]);
st[t] = true;
}
return res;
}
kruskal(克鲁斯卡尔)算法过程:
- 将所有边按权重从小到大排
- 从小到大遍历所有边 ,不连通的边, 加入最小生成树
Kruskal 算法是按照边权排序,依次合并节点,并用并查集维护连通性。
#include <iostream>
#include<algorithm>
using namespace std;
const int N=2e5+10;
int n,m;
int q[N];
struct Edge{
int a,b,w;
bool operator< (const Edge &W)const
{
return w<W.w;
}
}edges[N];
int find(int x)
{
if(q[x]!=x) q[x]=find(q[x]);
return q[x];
}
int main()
{
cin>>n>>m;
for(int i=1;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++) q[i]=i;
int res=0,cnt=0;
for(int i=1;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)
{
res+=w;
q[a]=b;
cnt++;
}
}
if(cnt<n-1) puts("impossible");
else printf("%d\n",res);
return 0;
}
染色法 判断二分图
二分图一定不存在奇数回环
二分图任意一条边的两端的颜色一定不同
//染色法判断二分图
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10,M=2e5+10;
int n,m;
int h[N],e[N],ne[N],idx;
int color[N];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
bool dfs(int u,int c)
{
color[u]=c;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!color[j])
if(!dfs(j,3-c)) return false;
else if(color[j]==c) return false;
}
return true;
}
int main()
{
cin>>n>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
bool flag=true;
for(int i=1;i<=n;i++)
{
if(!color[i])
{
if(!dfs(i,1))
flag=false;
break;
}
}
if(flag=true) puts("yes");
else puts("no");
return 0;
}
匈牙利算法
对于二分图,求最大匹配数,为每个点配对,一一对应
//匈牙利算法 最大匹配数
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e5+10;
int n1,n2,m;
int e[N],ne[N],h[N],idx;
int match[N];
bool st[N];
void add(int a,int b)
{
e[idx]=b;ne[idx]=h[a],h[a]=idx++;
}
bool find(int x)
{
for(int i=h[x];i!=-1;i=ne[i])
{
int j=e[i];
if(!st[j])
{
st[j]=true;
if(match[j]==0||find(match[j]))
{
match[j]=x;
return true;
}
}
}
return false;
}
int main()
{
cin>>n1>>n2>>m;
memset(h,-1,sizeof h);
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
}
int res=0;
for(int i=1;i<=n1;i++)
{
memset(st,false,sizeof st);
if(find(i)) res++;
}
printf("%d\n",res);
return 0;
}