并查集、实验六 图的应用

  • 树的并查算法
  • 实验六 图的应用  CCF-201709-4 通信网络

一、树的并查算法
使用并查集一般都有优化,合并和压缩,有的合并考虑树的高度,有的合并考虑根结点的权值等等。
在这个例子中,用编号代表每个元素,数组array表示的是父亲的编号,par[x]=x时,x是所在的树的根。
1、ParPtrTree.h

#include
using namespace std;
#ifndef _ParPtrTree
#define _ParPtrTree
namespace wangzhe
{
	class ParPtrTree
	{
		private:
			int *array;
			int size;
		public:
			ParPtrTree(int sz);
			~ParPtrTree();
			int FIND(int curr) const;
                        void UNION(int a,int b);
                        bool same(int a,int b);		
	};
}
#endif 

2、ParPtrTree.cpp

#include
using namespace std;
#include"ParPtrTree.h"
namespace wangzhe
{
	ParPtrTree::ParPtrTree(int sz)
	{
		size=sz;
		array=new int[sz];
		for(int i=0;i

3、main.cpp

#include 
using namespace std; 
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
#include"ParPtrTree.h"
using namespace wangzhe;
int main(int argc, char** argv) 
{
	ParPtrTree *ppt=new ParPtrTree(100);
	cout<same(3,1)<FIND(3)<FIND(1)<UNION(3,1);
	cout<same(3,1)<FIND(3)<FIND(1)<

4、运行结果
并查集、实验六 图的应用_第1张图片

 

二、实验六 图的应用  CCF-201709-4 通信网络

删除(注释)了部分无用的代码,添加了一些数据成员和方法,此为提交判分的版本,一开始拿了5分,修修改改甚至拿了0分(崩溃)
并查集、实验六 图的应用_第2张图片
想了N载春秋,最后在什造大佬的提点下,醍醐灌顶,原来是SetEdge方法添加边时若两个顶点相同的话,原先的代码会给出提示信息:“Illegal Vertex”。遂将这句提示信息给注释掉再提交,60分,剩下四个样例超时了,应该用邻接表的,但已经满足老师规定的要求了遂不再费时修改。

看来这数据还是有点意思。
满分可以参考以前写的这篇CCF-CSP-201709-4 通信网络

60分超时代码:

//CSDN博客:https://blog.csdn.net/qq_40889820
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,b,sizeof(a))
//#define e 2.71828182
#define VISITED 1//标记状态,设为1 
#define UNVISITED 0//未标记状态,设为0 
#define INF 1<<30//无穷大,设为1<<30 
#define Pi 3.141592654
using namespace std;//标准命名空间 
class Graph
{
        private:
		void operator = (const Graph&) {}
		Graph(const Graph&) {}
	public:
		Graph() {}//构造函数 
		virtual ~Graph() {}//析构函数 
		virtual int n() =0;//顶点数目 
		//virtual int e() =0;//边数目 
		virtual int first(int v) =0;//与顶点v关联的第一条边 
		virtual int next(int v,int w) =0;//与顶点v关联的在顶点w后的下一条边 
		virtual void clear()=0;//销毁一个图 
		virtual bool setEdge(int v1,int v2,int wght) =0;//设边权 
		//virtual bool delEdge(int v1,int v2) =0;//删除边 
		//virtual bool isEdge(int i,int j) =0;//判断是否有边 
		//virtual int weight(int v1,int v2) =0;//v1-v2边的边权 
		virtual int getMark(int v) =0;//返回标记信号 
		virtual void setMark(int v,int val) =0;//标记数组中做标记 
		//virtual void DFS(Graph *G,int v) =0;//深搜 
};

class Graphm:public Graph
{
	private:
		int numVertex,numEdge;//顶点数、边数 
		int **matrix;//邻接矩阵 
		int *mark;//标记数组
		int **iskno; 
	public:
		Graphm();//无参构造函数 
		~Graphm();//析构函数 
		void Init(int n);//初始化 
		int n();//返回顶点数 
		//int e();//返回边数 
		int first(int v);//与顶点v第一个相关联的边 
		int next(int v,int w);//与顶点v在顶点w后相关联的边 
		void clear();//清空 
		bool setEdge(int v1,int v2,int wt);//增添边或修改边 
		//bool delEdge(int v1,int v2);//删除边 
		//bool isEdge(int i,int j);//判断是否是边 
		//int weight(int v1,int v2);//返回权值 
		int getMark(int v);//返回标记状态 
		void setMark(int v,int val);//标记 
                void memset();//重置mark数组 
		//void DFS(Graph *G,int v);//深度优先搜索 
		//void print();//输出邻接矩阵
		void fun(int v1,int v2);//求出第v1个部门知道的部门
		int solve();//求解 
};  
  
Graphm::Graphm()
{
		
}
	
Graphm::~Graphm()
{
	clear(); 
}
	
void Graphm::Init(int n)
{
	numVertex=n;
	numEdge=0;
	mark=new int[n];
	for(int i=0;i=numVertex||v2>=numVertex)
	{
		cout<<"Illegal vertex\n";
		return false;
	}*/
	if(matrix[v1][v2]==INF) numEdge++;
	matrix[v1][v2]=wt;
	return true;
}
			
int Graphm::getMark(int v)
{
	return mark[v];
}
	
void Graphm::setMark(int v,int val)
{
	mark[v]=val;
}
	
void Graphm::memset()
{
	for(int i=0;i>N>>M;//输入 
	G.Init(N);//N个部门 
	for(int i=0;i>a>>b;//输入
		a--;b--;//图的实现里顶点数是0到n-1,而题目中是1到n,所以需要转换一下 
		G.setEdge(a,b,1);//邻接矩阵matrix[a][b]置为1 
	}
	
	for(int i=0;i

 

你可能感兴趣的:(∨∨坑逼数据结构课)