图相关算法

//头文件省略
struct Edge
{
	int from, to, val;
	Edge(int f = 0, int t = 0, int v = 0) : from(f), to(t), val(v) {}
};

struct Graph
{
	vector<vector<int>> graph;//邻接表
	vector<vector<int>> weights;//邻接矩阵
	vector<Edge> edges; //边集
	int p_num;
	Graph(int point_num) : p_num(point_num), graph(point_num + 1, vector<int>(0)), 
			weights(point_num + 1, vector<int>(point_num + 1, -1)), edges(0) {
		for(int i = 1; i <= point_num; ++i)
			weights[i][i] = 0;
	}
	
	//from to 从1开始
	void add_dege(int from, int to, int weight)
	{
		graph[from].push_back(to);
		weights[from][to] = weight;
		edges.push_back(Edge(from, to, weight));
	}

	//并查集
	struct Union_find_set
	{
		vector<int> fa;
		int find(int x)
		{
			if(x != fa[x])
				fa[x] = find(fa[x]);
			return fa[x];
		}

		void unionn(int x, int y)
		{
			int fx = find(x), fy = find(y);
			fa[fx] = fy;
		}

		Union_find_set(int n) : fa(n + 1)
		{	
			for(int i = 1; i <= n; ++i)
				fa[i] = i;
		}
	};

	//Minimum Spanning Tree最小生成树,洛谷p3366通过
	int MST_Kruskal()
	{
		int ret = 0;
		vector<bool> vis(p_num + 1, false);

		sort(edges.begin(), edges.end(), [](Edge &e1, Edge &e2) {return e1.val < e2.val; } );

		Union_find_set st(p_num);
		for(auto &e : edges) //对每个边,检查两个点是否是一个连通块
		{
			int a = st.find(e.from), b = st.find(e.to);
			if( a != b) //不是一个连通块,返回值加上权重
			{
				st.unionn(a, b);
				ret += e.val;
			}
		}

		//如果图不连通
		for(int i = 1; i < p_num; ++i)
			if(st.find(i) != st.find(i+1))
				return -1;
		return ret;
	}
	
	//Minimum Spanning Tree最小生成树,洛谷p3366通过,注意重边
	int MST_Prim()
	{
		int ret = 0;
		struct dis {
			int x, val;
			dis(int x, int v) : x(x), val(v) {}
			bool operator < (const dis &d) const {return d.val < val; }
		};
		priority_queue<dis> q;

		vector<bool> vis(p_num + 1, false);
		vis[0] = true;

		q.push(dis(1, 0));
	
		while(!q.empty())
		{
			dis d = q.top(); q.pop();
			if(vis[d.x]) continue;

			vis[d.x] = true;
			ret += d.val;
			
			for(auto &a : graph[d.x])
			{
				if(vis[a] == false)
					q.push(dis(a, weights[d.x][a]));
			}
		}
		
		for(auto a : vis)
			if(a == false)
				return -1;
		
		return ret;
	}

	//多源最短路,leetcode 743通过
	vector<vector<int>> Floyd()
	{
		vector<vector<int>> dis = weights;
		
		for(int k = 1; k <= p_num; ++k)
			for(int i = 1; i <= p_num; ++i)
			{
				if(dis[i][k] == -1)
					continue;
				for(int j = 1; j <= p_num; ++j)
				{
					if(dis[k][j] == -1)
						continue;

					if(dis[i][j] == -1 || dis[i][k] + dis[k][j] < dis[i][j])
						dis[i][j] = dis[i][k] + dis[k][j];
				}
			}
		
		return dis;
	}

	//单源最短路,leetcode 743通过
	vector<int> Dijkstra(int start)
	{
		vector<bool> vis(p_num + 1, false);
		vector<int> dis(p_num + 1, 0x7fffffff);
		dis[start] = 0;

		struct node
		{
			int x, val;
			node(int x, int val) : x(x), val(val) {}
			bool operator < (const node &n) const {return n.val < val; }
		};
		priority_queue<node> q;

		q.push({start, 0});
		while(!q.empty())
		{
			node n = q.top(); q.pop();
			if(vis[n.x])	continue;
			vis[n.x] = true;

			for(auto &y : graph[n.x])
			{
				if(dis[n.x] + weights[n.x][y] < dis[y])
				{
					dis[y] = dis[n.x] + weights[n.x][y];
					q.push({y, dis[y]});
				}
			}
		}

		return dis;
	}

};

posted @ 2022-02-20 20:26  hellozhangjz  阅读(37)  评论(0)    收藏  举报