哈利·波特要考试了,他需要你的帮助。这门课学的是用魔咒将一种动物变成另一种动物的本事。例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等。反方向变化的魔咒就是简单地将原来的魔咒倒过来念,例如ahah可以将老鼠变成猫。另外,如果想把猫变成鱼,可以通过念一个直接魔咒lalala,也可以将猫变老鼠、老鼠变鱼的魔咒连起来念:hahahehe。
现在哈利·波特的手里有一本教材,里面列出了所有的变形魔咒和能变的动物。老师允许他自己带一只动物去考场,要考察他把这只动物变成任意一只指定动物的本事。于是他来问你:带什么动物去可以让最难变的那种动物(即该动物变为哈利·波特自己带去的动物所需要的魔咒最长)需要的魔咒最短?例如:如果只有猫、鼠、鱼,则显然哈利·波特应该带鼠去,因为鼠变成另外两种动物都只需要念4个字符;而如果带猫去,则至少需要念6个字符才能把猫变成鱼;同理,带鱼去也不是最好的选择。
输入格式:
输入说明:输入第1行给出两个正整数N (≤100)和M,其中N是考试涉及的动物总数,M是用于直接变形的魔咒条数。为简单起见,我们将动物按1~N编号。随后M行,每行给出了3个正整数,分别是两种动物的编号、以及它们之间变形需要的魔咒的长度(≤100),数字之间用空格分隔。
输出格式:
输出哈利·波特应该带去考场的动物的编号、以及最长的变形魔咒的长度,中间以空格分隔。如果只带1只动物是不可能完成所有变形要求的,则输出0。如果有若干只动物都可以备选,则输出编号最小的那只。
输入样例:
6 11
3 4 70
1 2 1
5 4 50
2 6 50
5 6 60
1 3 70
4 6 60
3 6 80
5 1 100
2 4 60
5 2 80
输出样例:
4 70
/*哈利·波特的考试*/
/*思路:1.判断是不是连通图,如果不是则输出0;
2.多源最短路径,对联通图中的每一个顶点遍历,得到每一个顶点与其他顶点的最大长度*/
/*邻接矩阵,无向图*/
/*1.忘记加取址符
2.错在对角线没有初始为0
3.无解的输出位置错误
*/
#include<stdio.h>
#include<stdlib.h>
typedef struct Gnode* MGraph;
struct Gnode {
int Nv; /*顶点数*/
int Ne; /*边数*/
int G[101][101]; /*权重*/
};
/*边的定义,无权边*/
typedef struct Enode* Edge;
struct Enode {
int V1, V2;
int weight;/*权重*/
};
/*队列操作*/
typedef struct Qnode* ptrtoQnode;
struct Qnode {
int* Data;/*data数组,*/
int front, rear;/*队列头尾指针*/
int maxsize;/*容量*/
};
typedef ptrtoQnode Queue;
int AddQ(Queue Q, int x);
Queue CreateQueue(int maxsize);
int isempty(Queue Q);
int DeleteQ(Queue Q);
/*操作函数*/
MGraph creatgraph(int size);
void insert(MGraph g, Edge e);
MGraph buildgraph(int N);
int isedge(MGraph graph, int a, int b);
void BFS(MGraph graph, int N, int* visited, int s);
void Floyd(MGraph graph,int weight[][101]);
/*队列操作*/
int AddQ(Queue Q, int x);
Queue CreateQueue(int maxsize);
int isempty(Queue Q);
int DeleteQ(Queue Q);
int main() { /*注意此题从1开始*/
int N;
scanf("%d", &N);
int* visited = (int*)malloc((N+1) * sizeof(int));
int isanswer = 1;
for (int i = 1; i < N+1; i++) {
visited[i] = 0;
}
/*建立邻接矩阵*/
MGraph graph = buildgraph(N);
BFS(graph, N, visited, 1);/*以第一个顶点为起点,对图进行遍历,如果图中有顶点未被遍历过则说明不是联通图*/
for (int i = 1; i < N + 1; i++) {
if (visited[i] == 0) {
isanswer = 0;
break;
}
}
/*多源最短路径*/
int weight[101][101];
int shortest[101];
Floyd(graph, weight);
for (int i = 1; i < N + 1; i++) {
int max = -1;
for (int j = 1; j < N + 1; j++) {
if (weight[i][j] > max && weight[i][j] != 20000) {
max = weight[i][j];
}
}
shortest[i] = max;/*将与第i个顶点路径最长的存储*/
}
/*先将shortest存储*/
int data[101];
for (int i = 1; i < N + 1; i++) {
data[i] = shortest[i];
}
/*对shortest排序,找出其最小值*/
int j;
int temp;
for (int i = 1; i < N ; i++) { /*shortest最小值即第一元素*/
for (j = i + 1; j < N + 1; j++) {
if (shortest[i] > shortest[j]) {
temp = shortest[i];
shortest[i] = shortest[j];
shortest[j] = temp;
}
}
}
/*找出最小编号*/
int answer;
for (int i = 1; i < N + 1; i++) {
if (shortest[1] == data[i]) {
answer = i;
break;
}
}
if(isanswer == 1){
printf("%d %d", answer, data[answer]);
}
else printf("0");
return 0;
}
MGraph creatgraph(int size) {/*初始化邻接矩阵*/
int j;
MGraph graph = (MGraph)malloc(sizeof(struct Gnode)); /*建图*/
graph->Nv = size;
graph->Ne = 0;
/*初始化邻接矩阵*/
for (int i = 1; i < graph->Nv+1; i++) {
for (j = 1; j < graph->Nv+1; j++) {
if(i==j){ /*一开始没有将对角线处初始为0,导致最后多源最短路径出错*/
graph->G[i][j] = 0;
}
else{
graph->G[i][j] = 20000; /*设20000为无穷值,即两点不连通*/
}
}
}
return graph;
}
void insert(MGraph g, Edge e) { /*注意此题为无向图*/
g->G[e->V1][e->V2] = e->weight;
g->G[e->V2][e->V1] = e->weight;
}
MGraph buildgraph(int N) {
MGraph G;
G = creatgraph(N);
scanf("%d", &G->Ne);
if (G->Ne != 0) {
Edge E = (Edge)malloc(sizeof(struct Enode));
for (int i = 0; i < G->Ne; i++) {
scanf("%d %d %d", &E->V1, &E->V2,&E->weight);
insert(G, E);
}
}
return G;
}
Queue CreateQueue(int maxsize) {
Queue Q = (Queue)malloc(sizeof(struct Qnode));
Q->Data = (int*)malloc(maxsize * sizeof(int));
Q->front = Q->rear = 0;
Q->maxsize = maxsize;
return Q;
}
int AddQ(Queue Q, int x) {
Q->rear = (Q->rear + 1) % (Q->maxsize);
Q->Data[Q->rear] = x;
return 1;
}
int isempty(Queue Q) {
return(Q->rear == Q->front);
}
int DeleteQ(Queue Q) {
Q->front = (Q->front + 1) % Q->maxsize;
return Q->Data[Q->front];
}
int isedge(MGraph graph, int a, int b) {
return graph->G[a][b] < 20000 ? 1 : 0;
}
void BFS(MGraph graph, int N, int* visited, int s) {
Queue Q;
int v, w;
Q = CreateQueue(N);
visited[s] = 1;
AddQ(Q, s);
while (isempty(Q) == 0) {
v = DeleteQ(Q);
for (w = 1; w < graph->Nv + 1; w++) {/*遍历图中的每一个顶点*/
if (visited[w] == 0 && isedge(graph, v, w)==1) {
visited[w] = 1;
AddQ(Q, w);
}
}
}
}
void Floyd(MGraph graph,int weight[][101]) {
int i, j, k;
for (i = 1; i < graph->Nv + 1; i++) {
for (j = 1; j < graph->Nv + 1; j++) {
weight[i][j] = graph->G[i][j];
}
}
for (k = 1; k < graph->Nv + 1; k++) {
for (i = 1; i < graph->Nv + 1; i++) {
for (j = 1; j < graph->Nv + 1; j++) {
if (weight[i][k] + weight[k][j] < weight[i][j]) {
weight[i][j] = weight[i][k] + weight[k][j];
}
}
}
}
}