首页 > 其他分享 > 图论四道题目

图论四道题目

时间:2023-04-18 14:25:08浏览次数:24  
标签:四道 图论 题目 vernum int return ++ 顶点 100

图论OJ

A.最小生成树
Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 14
(6 users)Total Accepted: 6 (5 users)Special Judge: No
Description
根据输入构建无向带权图,并利用kruskal法求出最小生成树,输出该
最小生成树的各边权值和。
Input
输入第一行为:结点数和边(或弧)的数目; 第二行为各结点名;第
三行为各边的权值。输出为:最小生成树的各边权值和。
Sample Input
5 7
A B C D E
A B 10
A C 8
A E 3
B C 2
B D 5
C E 7
D E 4
Sample Output
14
Hint
输出有换行符。
#include<iostream>
#include<algorithm>
#include<math.h>
#include<cstdio>
int mark[100];      //全局变量 并查集
using namespace std;
typedef struct node
{
	int ii, jj;
	int cost;
}Node;
bool cmp(Node x,Node y)
{
	return x.cost< y.cost;
 }
int Comproot(int x) {
	if (x == mark[x])
		return x;
	else
		return Comproot(mark[x]);
}

int main()
	{
	int v, e;
	char ss[100];
	Node node[100];
	for (int i = 0; i < 100; i++)
	{
		mark[i] = i;               //初始化并查集 并用下标为其赋值
	}
	cin >> v >> e;
	for(int i = 0; i < v; i ++){
        cin>>ss[i];
	}
	char aa,bb;
	for (int i = 0; i < e; i++)
	{
	    cin>>aa>>bb>>node[i].cost;
	    for(int j = 0; j < 100; j++){
            if(ss[j] == aa){
                node[i].ii = j+1;
            }
            if(ss[j] == bb){
                 node[i].jj = j+1;
            }
	    }
	}
	sort(node, node + e, cmp);
	int sum = 0;
	for (int i = 0; i < e; i++)
	{
		int a = Comproot(node[i].ii);
		int b = Comproot(node[i].jj);
		if (a == b)
			continue;
		mark[a] = b;
		sum = sum + node[i].cost;
	}
	cout << sum<<endl;
	return 0;
	}
B.图的广度优先搜索
Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 15
(6 users)Total Accepted: 6 (6 users)Special Judge: No
Description
根据输入建立无向图,利用邻接表法对该图进行广度优先搜索,并输
出遍历序列。
Input
说明:输入第一行为结点数和边(或弧)的数目;第二行为结点的值;
第三行值最后为该图的弧(边);默认广度优先遍历从第一个结点出发。
Output
输出为广度优先遍历序列。
Sample Input
5 5
A B C D E
A B
B C
B E
C D
D E
Sample Output
A B C E D
Hint
输出有换行符
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
//#define GRAPH_LIST

int* g_visited;  //访问标志
int* g_queue;  //定义一个队列Q
int g_front = -1, g_rear = -1;         //初始化队列Q
int g_queue_size;
int g_vernum;
int g_arcnum;

typedef struct VNode    //头结点的类型定义
{
	char  data[100];   //用于存储的顶点
	int nextver_index;       //边指向的顶点的位置
	struct VNode* nextver_point;   //指示下一个与该顶点相邻接的顶点
}AdjList;
typedef struct            //图的类型定义
{
	AdjList* vertex;  //用于存储顶点
	int* arcs;                //邻接矩阵,存储边的信息
	int vernum, arcnum;             //顶点数和边的数目
}MGraph;

void Visited_init(MGraph* N)
{
	int v;
	for (v = 0; v < g_vernum; v++)
	{
		g_visited[v] = 0;   //访问标志数组初始化为未被访问
	}
	return;
}

void CreateGraph_T(MGraph* N)    //邻接矩阵表示
{
	int i, j, k;
	char aa, bb;
	//初始化邻接矩阵边的信息初始化为空
	memset((char*)N->arcs, 0, 4 * g_vernum * g_vernum);
	for (i = 0; i < g_vernum; i++)
	{
		cin >> N->vertex[i].data;
	}

	for (k = 0; k < g_arcnum;)
	{
		cin >> aa >> bb;
		for (int t = 0; t < g_vernum; t++) {
			if (N->vertex[t].data[0] == aa) {
				i = t;
			}
			if (N->vertex[t].data[0] == bb) {
				j = t;
			}
		}
		if (i >= g_vernum || j >= g_vernum)
		{
			printf("第 %d 条边的两个顶点序号(逗号隔开): 输入错误,请重新输入\t\n\n", k + 1);
			continue;
		}
		N->arcs[i * g_vernum + j] = 1;
		N->arcs[j * g_vernum + i] = 1;
		k++;
	}

}

void Visit1(char* v)   //访问函数,输出图中的顶点
{
	printf(" %s", v);
}
void Visit(char* v)   //访问函数,输出图中的顶点
{
	printf("%s", v);
}
int Visited_set(int key)
{
	g_visited[key] = 1;    //设置访问标志为1,表示已经被访问过
	return 0;
}
int Visited_get(int key)
{
	return g_visited[key];
}
int Enqueue(int key)
{
	g_rear++;
	g_queue[g_rear % g_queue_size] = key;    //v入队列 g_rear进队口
	return 0;
}
int Dequeue(void)
{
	g_front++;
	return g_queue[g_front % g_queue_size];   //队首元素出队赋值给v
}
int Queue_empty()
{
	return g_front == g_rear;
}
int Queue_full()
{
	return (g_rear - g_front) == g_queue_size;
}
void Queue_init()
{
	g_front = -1;
	g_rear = -1;         //初始化队列Q
}

void BFS_T(MGraph* N)
{
	int j;
	int t = 0;
	while (!Queue_empty() && !Queue_full())  //如果队列不空
	{
		t = Dequeue();   //队首元素出队赋值给v
		for (j = 1; j < g_vernum; j++)
		{
			if (N->arcs[t * g_vernum + j] == 1)
			{
				if (Visited_get(j) == 0)  //如果该顶点未被访问过
				{
					Visited_set(j);
					Visit1(N->vertex[j].data);
					Enqueue(j);
				}
			}
		}

	}
}
void BFSTraverse_T(MGraph* N)  //从第一个顶点出发,按广度优先非递归搜索图N
{

	int v;
	Visited_init(N);
	Queue_init();

	for (v = 0; v < g_vernum; v++)
	{
		if (Visited_get(v) == 1)
		{
			continue;
		}
		Visited_set(v);
		Visit(N->vertex[v].data);
		Enqueue(v);
		BFS_T(N);
	}
	cout << endl;
}
int GraphInit(MGraph* N)
{
	g_queue_size = g_vernum * g_vernum;
	/*初始化邻接表*/
	N->vertex = (AdjList*)malloc(sizeof(AdjList) * g_vernum);
	/*初始化邻接矩阵*/
	N->arcs = (int*)malloc(sizeof(int) * g_vernum * g_vernum);
	/*初始化访问标志*/
	g_visited = (int*)malloc(sizeof(int) * g_vernum);
	/*初始化队列*/
	g_queue = (int*)malloc(sizeof(int) * g_queue_size);

	if (N->vertex == NULL || N->arcs == NULL
		|| g_visited == NULL || g_queue == NULL)
	{
		return -1;
	}

	return 0;
}
int GraphRelease(MGraph* N)
{

#ifdef GRAPH_LIST
	int i;
	AdjList* p;
	AdjList* t;
	for (i = 0; i < g_vernum; i++)
	{
		printf("%s[%d]", N->vertex[i].data, i);
		p = N->vertex[i].nextver_point;   //将p指向边表的第一个结点
		while (p != &N->vertex[i])
		{
			t = p;
			p = p->nextver_point;
			free(t);
		}
	}
#endif
	free(N->arcs);
	free(g_visited);
	free(g_queue);
	free(N->vertex);
	return 0;

}
int  main()
{
	int ret;
	MGraph N;
again:
	cin >> g_vernum;
	cin >> g_arcnum;
	if (g_vernum == 0 || g_arcnum == 0)
	{
		goto again;
	}

	ret = GraphInit(&N);
	if (ret == -1)
	{
		printf("程序初始化失败\n");
		return 0;
	}
#ifdef GRAPH_LIST
	printf("邻接表链表结构\n");
	CreateGraph_L(&N);
	DisplayGraph_L(&N);
	BFSTraverse_L(&N);
	DFSTraverse_L(&N);

#endif
	CreateGraph_T(&N);
	BFSTraverse_T(&N);
	GraphRelease(&N);
	exit(0);
	return 0;
}
C.最短路径
Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 15
(6 users)Total Accepted: 6 (6 users)Special Judge: No
Description
题目内容:有n个村庄,现要选择在一个村庄中建立一所医院,使得该
医院到离其最远的村庄,距离最近。根据输入建立无向带权图,并利用
最短路径算法实现。
Input
输入第一行为村庄数和路径的数目;第二行为各村庄名;第三行至最
后为各村庄的距离。
Output
所选医院所在的村庄。
Sample Input
4 5
A B C D
A B 8
A D 6
B C 4
B D 5
C D 3
Sample Output
D
Hint
输出有换行符
//hospital.cpp
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
#define MAX 32767//定义一个很大的数当作是不存在直接路径的标志
int N = 0;
using namespace std;
typedef struct AM_Graph//图的邻接矩阵类型
{
    int AdjMatrix[100][100];//邻接矩阵存放各点之间的距离
    int VexNum,ArcNum;//存放顶点数量和弧的数量
    char VexName[100];//顶点名称
} AM_Graph;


void Floyd(AM_Graph g,int Dist[100][100])//Floyd算法求解各顶点之间的最短路径,传递的参数为存放有直接路径长度的矩阵
{
    int i,j,k;
    int count=0;//记录边的数量,方法是初始的矩阵所有不是0也不是MAX的元素个数可视为一条边

    for(i=0; i<N; i++)
        for(j=0; j<N; j++)
        {
            if((Dist[i][j]!=0)&&(Dist[i][j]!=MAX))
                count++;//记录边的个数
            g.AdjMatrix[i][j]=Dist[i][j];//用传递的二维数组为图的邻接矩阵赋值
        }
    g.VexNum=N;//为图的各项元素赋值
    g.ArcNum=count;
    for(k=0; k<N; k++) //用图中的每一点作为中间点遍历dist矩阵
    {
        for(i=0; i<N; i++)
        {
            for(j=0; j<N; j++)
            {
                if(Dist[i][j]>(Dist[i][k]+Dist[k][j]))//如果把k作为中间点会让距离变小
                {
                    Dist[i][j]=Dist[i][k]+Dist[k][j];//修改顶点之间的距离
                }
            }
        }
    }
}

void BuildEc(int Dist[100][100],int Ec[100])
{
    int i,j;
    int temp;//方便比较以便找出每一列的最大元素即为对应顶点的偏心度
    for(i=0; i<N; i++)
    {
        temp=Dist[0][i];//对每一列的偏心度取初始值
        for(j=0; j<N; j++)
        {
            if(temp<Dist[j][i])
                temp=Dist[j][i];//找到每一列的最大元素
        }
        Ec[i]=temp;
    }
}


int minEc(int Ec[100])//取得最小偏心度的顶点下标
{
    int i,temp,k;
    k=0;//下标赋初始值

    for(i=1; i<N; i++)
    {
        temp=Ec[k];//寻找最小偏心度元素
        if(temp>Ec[i])
        {
            k=i;//用k表示当前找到的偏心度最小元素的下标
        }
    }

    return k;//循环结束,返回遍历整个数组后偏心度最小的元素下标
}


void print(int Dist[100][100],int Ec[100],char VexName[100])//输出最终结果
{
    int k;
    k=minEc(Ec);//取得偏心度最小元素的下标
    printf("%c\n",VexName[k]);//输出结果
}



int main()
{
    int i,j;
    int x,y;
    int dist[100][100];
    memset(dist,-1,sizeof(dist));
    int EC[100];
    AM_Graph g;
    int n,v;
    cin>>N>>v;
    char aa,bb;
    for(i=0; i<N; i++)
        cin>>g.VexName[i];

    for(int j = 0; j < v; j ++)
    {
        cin>>aa>>bb;
        for(int t= 0; t < N; t++)
        {
            if(g.VexName[t] == aa)
            {
                x = t;
            }
            if(g.VexName[t] == bb)
            {
                y = t;
            }
        }
        scanf("%d",&dist[x][y]);
        dist[y][x] = dist[x][y];
    }

    for(i=0; i<N; i++) //没有直接距离的时候赋值为MAX
    {
        dist[i][i]=0;
        for(j=0; j<N; j++)
        {
            if(dist[i][j]<0)
                dist[i][j]=MAX;
        }
    }

    Floyd(g,dist);//为图赋值并且完成Floyd算法求解各顶点之间的最短路径
    BuildEc(dist,EC);//求解各点的偏心度并存放在一维数组里
    print(dist,EC,g.VexName);//输出最终结果

    return 0;
}
D.AOE网的关键路径
Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 3
(3 users)Total Accepted: 3 (3 users)Special Judge: No
Description
题目内容:对一个工程网,计算完成工程的最短工期。根据输入建立有
向带权图,并验证有向无环图,利用拓扑排序,求出关键路径,计算工期。
Input
输入第一行为结点数和边(或弧)的数目;第二行为各结点名称;第三
行至最后为带权的有向边。
Output
输出为:关键路径的关键活动权值和,即该工程的最短工期。
Sample Input
9 12
A B C D E F G H M
A B 3
A C 10
B D 9
B E 13
C E 12
C F 7
D G 8
D H 4
E H 6
F H 11
G M 2
H M 5
Sample Output
33
Hint
输出有换行符
#include<iostream>
using namespace std;

#define pointMax 100

struct VtNode                 //权值信息
{
	VtNode *nextVt;           //入度链表下一个结点
	int peace;                //入度下一顶点的值

	VtNode *nextVtt;          //出度链表下一个结点
	int peaceE;               //出度下一顶点的值

	int len;
};
struct PoNode                  //顶点信息
{
	char data;
	VtNode *firstPo;          //入度
	VtNode *Out;              //出度
};

struct ATgroup
{
	PoNode vertices[pointMax];     //每一个verticse代表一个顶点
	int point, vert;               //point顶点数,vert弧数
};

struct Node
{
	int data;
	Node *next;
};

struct SqStack          //栈
{
	Node *base;          //栈底
	Node *top;           //栈顶
	int data;
};

void Push(SqStack &S, int i)       //入栈
{
	Node *m = new Node;
	m->data = i;
	m->next = S.top;             //入栈过程
	S.top = m;
}

int Pop(SqStack &S)              //出栈
{
	int n = S.top->data;
	S.top = S.top->next;         //出栈过程
	return n;
}


int ATlocate(ATgroup A, char x)             //找到位置
{
	for (int i = 0; i < A.point; i++)       //依次遍历点的信息
	{
		if (A.vertices[i].data == x)        //找到x的位置
		{
			return i;
		}
	}
}

void show(ATgroup &A)                      //显示当前所有点入度出度的顶点
{
	//cout << endl;
	for (int i = 0; i < A.point; i++)
	{
		//cout << i;
		if (A.vertices[i].firstPo != NULL)          //入度位置
		{
		//	cout << "    " << A.vertices[i].firstPo->peace << "   ";
		}
		//else
		//	cout << "    -1" << "    ";

		if (A.vertices[i].Out != NULL)             //出度位置
		{
		//	cout << A.vertices[i].Out->peaceE << endl;
		}
		//else
		//	cout << "    -1" << endl;
	}
}

void CreatAT(ATgroup &A)
{
	cin >> A.point;
	cin >> A.vert;
	getchar();
	char q[100];
	for(int i = 0; i < A.point;i ++){
        cin>>q[i];
	}
	for (int i = 0; i < A.point; i++)
	{
		A.vertices[i].data = q[i];               //输入顶点值
		A.vertices[i].firstPo = NULL;            //初始化头结点为空
		A.vertices[i].Out = NULL;
	}
	char v1, v2; int m, n; int len;
	for (int i = 0; i < A.vert; i++)            //输入各边,构造邻接表
	{
		int Q;
		cin >> v1 >> v2 >> Q;
		m = ATlocate(A, v1);                  //确定位置
		n = ATlocate(A, v2);
		//第一个
		VtNode *p1 = new VtNode;
		VtNode *p2 = new VtNode;
		p1->peace = m;                             //入度
		p1->nextVt = A.vertices[n].firstPo;
		A.vertices[n].firstPo = p1;

		p2->peaceE = n;                            //出度
		p2->nextVtt = A.vertices[m].Out;
		p2->len = Q;
		A.vertices[m].Out = p2;
	}
	//show(A);
}

void FindIn(ATgroup *A, int *in)           //统计所有点的入度数并存入到in数组中
{
	int n = 0;
	for (int i = 0; i < A->point; i++)     //遍历每一个点
	{
		VtNode *p = new VtNode;
		p = A->vertices[i].firstPo;
		while (p != NULL)                  //将入度链表进行遍历
		{
			n++;
			p = p->nextVt;          //下一结点
		}
		in[i] = n;          //存入in数组
		n = 0;
	}
}

void SHOW(int *a, ATgroup *A)           //显示当前所有顶点入度数量还有几个
{
	for (int i = 0; i < A->point; i++)
	{
		//cout << a[i] << "  ";
	}
	//cout << endl;
}

int M[pointMax] = { 0 };
int topo[pointMax];           //拓扑遍历存入

void TPsort(ATgroup *A, SqStack &S)           //拓扑排序过程
{
	int Indegree[pointMax];
	FindIn(A, Indegree);             //将入度赋值给数组

	for (int i = 0; i < A->point; i++)
	{
		if (Indegree[i] == 0)         //将所有入度等于0的入栈
		{
			//cout << "Push=" << i << endl;
			Push(S, i);
		}
	}

	int m = 0;                //统计入度的顶点数
	int n, k;

	while (S.base != S.top)       //判断是否遍历完
	{
		//cout << endl;
		n = Pop(S);         //栈顶出栈
		//cout << "Pop=" << n << endl;
		topo[m] = n;        //存入topo
		m++;
		VtNode* p = new VtNode;
		p = A->vertices[n].Out;             //出度链表的结点
		while (p != NULL)            //遍历出度链表
		{
			k = p->peaceE;          //某结点的位置
			//cout << "出度下一结点k=" << k << endl;
			Indegree[k]--;          //将该结点顶点位置入度减一
			//SHOW(Indegree, A);       //显示当前所有点的入度
			if (Indegree[k] == 0)      //当等于0时,入栈
			{
				//cout << "Push=" << k << endl;
				Push(S, k);
			}
			p = p->nextVtt;     //下一个
		}
	}
}



int ve[pointMax];      //最早发生时间
int vl[pointMax];      //最晚发生时间

void CritPath(ATgroup *A)
{
	int n = A->point;          //n为顶点个数
	for (int i = 0; i < n; i++)        //将每个事件的最早事件为0
		ve[i] = 0;

	//---按拓扑次序求每个事件的最早发生时间---//
	int k, j;
	for (int i = 0; i < n; i++)
	{
		k = topo[i];                 //取的拓扑排序中的顶点序号
		VtNode *p = A->vertices[k].Out;     //指向K的第一个邻接结点
		while (p != NULL)
		{
			j = p->peaceE;
			if (ve[j] < ve[k] + p->len)
			{
				ve[j] = ve[k] + p->len;
			}
			p = p->nextVtt;
		}
	}
	cout << ve[n-1] << endl;

	for (int i = 0; i < n; i++)       //初始化
	{
		vl[i] = ve[topo[n - 1]];
	}
	//---按逆拓扑排序求每个事件的最迟发生时间----//
	for (int i = n - 1; i >= 0; i--)
	{
		k = topo[i];                 //取的拓扑排序中的顶点序号
		VtNode *p = A->vertices[k].Out;     //指向K的第一个邻接结点
		//cout << k << endl;
		while (p != NULL)
		{
			j = p->peaceE;
			if (vl[k] > vl[j] - p->len)
			{
				vl[k] = vl[j] - p->len;
				//cout << vl[k] << "  " << vl[j] << "   " << p->len << endl;
			}
			p = p->nextVtt;
		}
		//cout << vl[j] << endl;
	}


	//----判断每一活动是否为关键活动-----//
	int e, l;
	for (int i = 0; i < n; i++)
	{
		VtNode *p = A->vertices[i].Out;
		while (p != NULL)
		{
			j = p->peaceE;
			e = ve[i];
			l = vl[j] - p->len;
			p = p->nextVtt;
		}
	}
}

int main()
{
	ATgroup *A = new ATgroup;
	SqStack *S = new SqStack;
	S->top = S->base;
	S->data = pointMax;
	CreatAT(*A);
	TPsort(A, *S);
	CritPath(A);
	return 0;
}

标签:四道,图论,题目,vernum,int,return,++,顶点,100
From: https://www.cnblogs.com/Codingemon/p/17329369.html

相关文章

  • 图论基础
     P1266速度限制不难看出,这道题除了“有些道路没有速度限制”,就是一个裸的最短路。我们可以用分层图的思想,将速度\(v\)看做单独的一维,另\(dis[i][j]\)表示从起点到点\(i\),并且当前速度为\(j\)时的最短路。于是\(Dij\)的状态转移方程就是:当前边有速度限制时:\(dis[ver[i]......
  • java笔试题目——要求:仅打印出a=100,b=200,请写出method方法的代码
    //题目:publicclassTest{publicstaticvoidmain(String[]args){inta=10;intb=10;method(a,b);//需要在method方法被调用之后,仅打印出a=100,b=200,请写出method方法的代码。System.out.println("a="+a);S......
  • 图论
    207、课程表classSolution{publicList<Integer>[]edges;publicint[]ls;publicbooleanflag=true;publicbooleancanFinish(intnumCourses,int[][]prerequisites){edges=newList[numCourses];for(inti=0;i<......
  • 总结与归纳之图论
    (再开一个大坑好吧)前言总论+前置概念正文树上问题大杂烩拓扑序短路问题大杂烩生成树问题大杂烩斯坦纳树分层图差分约束连通性问题大杂烩欧拉/哈密顿路问题大杂烩二分图图匹配问题大杂烩网络流问题大杂烩特殊图问题大杂烩......
  • 算法基础模板整理(基础图论篇)
    拓扑排序bool topo(){    queue<int> q;    for(int u = 1; u <= n; u ++ )        if(!ind[u]) q.push(u);        int cnt = 0;    while(!q.empty()){        int u = q.front();        q.pop(); ......
  • 优化 PMU 放置 (OPP) 问题的六种算法,包括两种模拟退火方法、两种图论过程和递归安全 N
    PMU优化配置 系统完全可观软件:MATLAB优化PMU放置(OPP)问题的六种算法,包括两种模拟退火方法、两种图论过程和递归安全N算法。 从MatPower获得的IEEE14,30,39,57和118bus系统数据,可得出系统完全可观所需配置pmu数量以及对应位置。配有对应文献ID:16150671665749743......
  • 一、图论基础知识(2023.4.13初版[个人向])
    1.图的定义和概念1.图的定义图(Graph)是由顶点的有穷非空集合V和顶点之间的边的集合E组成,通常表示为G={V,E},其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合1.图中点的数据元素称之为顶点线性表中的数据元素称为元素数中的数据元素称为结点2.线性表和树均可以没有元素,......
  • 【图论之拓扑排序】剑指 Offer II 114. 外星文字典
    剑指OfferII114.外星文字典讲解传送门constintN=26,M=N*N;classSolution{public:inth[N],e[M],ne[M],idx=0;boolst[N];intin[N],cnt=0;//上面三行要写在classSolution内部,不然每次调用不会清空voidadd(inta,intb){......
  • 结对编程-小学生四则运算题目生成
    这次结对编程我是跟学号为2152520的朋友一起进行的四则运算题目生成的编程的。这次我们采用的编程语言是c++编程要求为:题目均为两次的运算,大小限制在一百以内的数字,且答案需要坐落在0~100之间(不显示出答案)。代码演示:#include<iostream>#include<cstdlib>usingnamespacest......
  • 【code】图论
    图一幅图是由节点和边构成的,逻辑结构如下:所以图的逻辑结构为:/*图节点的逻辑结构*/classVertex{intid;Vertex[]neighbors;}一般边的表示,有两种实现方式,一种是邻接表,一种是邻接矩阵邻接表很直观,我把每个节点x的邻居都存到一个列表里,然后把x和这个......