//时间复杂度O(n^3)
初始化:
for(int i =1; i <= n; i ++)for(int j =1; j <= n; j ++)if(i == j) d[i][j]=0;else d[i][j]= INF;// 算法结束后,d[a][b]表示a到b的最短距离voidfloyd(){for(int k =1; k <= n; k ++)for(int i =1; i <= n; i ++)for(int j =1; j <= n; j ++)
d[i][j]=min(d[i][j], d[i][k]+ d[k][j]);}
朴素prim
//时间复杂度O(n^2+m)int n;// n表示点数int g[N][N];// 邻接矩阵,存储所有边int dist[N];// 存储其他点到当前最小生成树的距离bool st[N];// 存储每个点是否已经在生成树中// 如果图不连通,则返回INF(值是0x3f3f3f3f), 否则返回最小生成树的树边权重之和intprim(){memset(dist,0x3f,sizeof dist);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;}
kruskal
//时间复杂度O(mlogm)int n, m;// n是点数,m是边数int p[N];// 并查集的父节点数组struct Edge // 存储边{int a, b, w;booloperator<(const Edge &W)const{return w < W.w;}}edges[M];intfind(int x)// 并查集核心操作{if(p[x]!= x) p[x]=find(p[x]);return p[x];}intkruskal(){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)return INF;return res;}
染色体法判断二分图
//时间复杂度O(n+m)int n;// n表示点数int h[N], e[M], ne[M], idx;// 邻接表存储图int color[N];// 表示每个点的颜色,-1表示未染色,0表示白色,1表示黑色// 参数:u表示当前节点,c表示当前点的颜色booldfs(int u,int c){
color[u]= c;for(int i = h[u]; i !=-1; i = ne[i]){int j = e[i];if(color[j]==-1){if(!dfs(j,!c))returnfalse;}elseif(color[j]== c)returnfalse;}returntrue;}boolcheck(){memset(color,-1,sizeof color);bool flag =true;for(int i =1; i <= n; i ++)if(color[i]==-1)if(!dfs(i,0)){
flag =false;break;}return flag;}
匈牙利算法
//时间复杂度O(nm)int n1, n2;// n1表示第一个集合中的点数,n2表示第二个集合中的点数int h[N], e[M], ne[M], idx;// 邻接表存储所有边,匈牙利算法中只会用到从第一个集合指向第二个集合的边,所以这里只用存一个方向的边int match[N];// 存储第二个集合中的每个点当前匹配的第一个集合中的点是哪个bool st[N];// 表示第二个集合中的每个点是否已经被遍历过boolfind(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;returntrue;}}}returnfalse;}// 求最大匹配数,依次枚举第一个集合中的每个点能否匹配第二个集合中的点int res =0;for(int i =1; i <= n1; i ++){memset(st,false,sizeof st);if(find(i)) res ++;}