2022.2.15 学习总结

1.学习图的最小生成树

简单说来大概可以将“最小生成树”视作“最短路”+“树式结构”,而“最短路”与“树”我们都已经有了些基础,学这个也就感觉没那么难了。

2.做题

(1).【模板】单源最短路径(弱化版) - 洛谷
 

昨天晚一点的时候终于把这题整出来了。

链式前向星的存储结构就类似于链表,就是上图右侧的样子。

其中to记录“指向的节点”,w表示“两点间的边的权值”,next则是记录数组下标作为指针来连接各节点,而head数组就是起到更新指针的作用

清楚链式前向星的存储原理后就能把这题做出来了。

#include <bits/stdc++.h>
using namespace std;
struct Edge {
	int v,w,nxt;
};
Edge e[500010];
int head[100010],cnt=0;

inline void addEdge(int u,int v,int w) {
	e[++cnt].v=v;
	e[cnt].w=w;
	e[cnt].nxt=head[u];
	head[u]=cnt;
}

int n,m,s;
int dis[100010];

struct node { //堆节点
	int u,d;
	bool operator <(const node& rhs) const {
		return d>rhs.d;
	}
};

inline void Dijkstra() {
	for ( int i=1; i<=n; i++) dis[i]=2147483647;
	dis[s]=0;
	priority_queue<node> Q; //堆
	Q.push((node) {
		s,0
	});
	while (!Q.empty()) {
		node fr=Q.top();
		Q.pop();
		int u=fr.u,d=fr.d;
		if (d!=dis[u]) continue;
		for ( int i=head[u]; i; i=e[i].nxt) {
			int v=e[i].v,w=e[i].w;
			if (dis[u]+w<dis[v]) {
				dis[v]=dis[u]+w;
				Q.push((node) {
					v,dis[v]
				});
			}
		}
	}
}

int main() {
	cin>>n>>m>>s;
	int X,Y,Z;
	for ( int i=1; i<=m; i++) {
		cin>>X>>Y>>Z;
		addEdge(X,Y,Z);
	}
	Dijkstra();
	for ( int i=1; i<=n; i++) printf("%d ",dis[i]);
	return 0;
}

(2).【模板】最小生成树 - 洛谷

 经典模板题,就不解释了,注意一下如果无法找到最小生成树,就要输出“orz”

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct edge
{
    int u,v,w;
}e[1000100];/*用一个结构体存储边的关系.数组大小需比边数大1*/
int n,m,parent[200100],sum,count1;/*并查集需要用到的变量。f【】数组大小需比点数大1*/
bool cmp(struct edge a,struct edge b)
{
    if(a.w < b.w) return 1;
    else          return 0;
}
int find(int x)/*查找父节点*/
{
    if(parent[x] != x)
    parent[x] = find(parent[x]);
    return parent[x];
}
int union_parent(int x,int y)/*连接两节点*/
{
    if(find(x) != find(y))
    { parent[find(y)]=find(x); return 1;}
    else           return 0;

}
int main()
{
    int i,j,k;
    cin>>n>>m;/*n个顶点,m条边*/
    for(i=1;i<=m;i++)
    cin>>e[i].u>>e[i].v>>e[i].w;
    sort(e+1,e+m+1,cmp);/*对结构体降序排序*/
    // for(i=1;i<=m;i++)         //输出检查排序
    // cout<<e[i].u<<"  "<<e[i].v<<" "<<e[i].w<<endl;
    /*并查集初始化*/
    for(i=0;i<=n;i++)
    parent[i]=i;
    for(i=1;i<=m;i++)
    {
        /*判断一条边的两个顶点是否连通,即判断是否在同一个集合中*/
        if( union_parent(e[i].u,e[i].v) )/*非0即连通*/
        {
            count1++;
            sum+=e[i].w;
        }
        if(count1 == n-1) break;/*选用n-1条边后退出循环*/
    }
    for(i=2;i<=n;i++)
    if(find(parent[i-1]) != find(parent[i])) {cout<<"orz"<<endl;system("pause");return 0;}
    cout<<sum<<endl;
    system("pause");
    return 0;
}

(3).拆地毯 - 洛谷

也是道模板题,对“美丽度”进行排序后求树就好了,只不过这里要求的是“最大生成树”

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
struct edge
{
    int u,v,w;
}e[100100];/*用一个结构体存储边的关系.数组大小需比边数大1*/
int n,m,k,parent[100100],sum,count1;/*并查集需要用到的变量。f【】数组大小需比点数大1*/
bool cmp(struct edge a,struct edge b)
{
    if(a.w > b.w) return 1;
    else          return 0;
}
int find(int x)/*查找父节点*/
{
    if(parent[x] != x)
    parent[x] = find(parent[x]);
    return parent[x];
}
int union_parent(int x,int y)/*连接两节点*/
{
    if(find(x) != find(y))
    { parent[find(y)]=find(x); return 1;}
    else           return 0;

}
int main()
{
    int i,j,v;
    cin>>n>>m>>k;/*n个顶点,m条边*/
    for(i=1;i<=m;i++)
    cin>>e[i].u>>e[i].v>>e[i].w;
    sort(e+1,e+m+1,cmp);/*对结构体升序排序*/
    // for(i=1;i<=m;i++)         //输出检查排序
    // cout<<e[i].u<<"  "<<e[i].v<<" "<<e[i].w<<endl;
    /*并查集初始化*/
    for(i=0;i<=n;i++)
    parent[i]=i;
    for(i=1;i<=m;i++)
    {
        /*判断一条边的两个顶点是否连通,即判断是否在同一个集合中*/
        if( union_parent(e[i].u,e[i].v) )/*非0即连通*/
        {
            count1++;
            sum+=e[i].w;
        }
        if(count1 == k) break;/*选用n-1条边后退出循环*/
    }
    cout<<sum<<endl;
    system("pause");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值