标签:四道 图论 题目 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