题意:即找所给字符串组成的饮料名是否组成环
涉及知识:
1、链表
2、拓扑排序
3、STL 中 map、stack的应用(当然也可以自己实现,不太建议,当然没事儿写来练手当然行)
详细注释见代码:
#include<cstdio>
#include<iostream>
#include<map>
#include<stack>
#include<cstdlib>
#include<string>
#include<cstring>
using namespace std;
///链表存图
typedef struct Edge ///一条边的后顶点
{
int toE;
Edge *next = NULL; ///指向下一条以Vnum为前顶点的,后定点的位置
}Edge;
typedef struct Vnum ///每条边的前定点
{
int data;
Edge *firstEdge = NULL;
}Vnum;
Vnum V[10010];
int indegree[10010];///每个定点的入度
stack<int > innum;
///拓扑排序
int tuopo(int num)
{
int countt = 0;
memset(indegree, 0, sizeof(indegree));///初始化每个定点的入度为0
///计算每个定点的入度:
for(int i = 0; i < num; i++)
{
Edge *temp = V[i].firstEdge;
while(temp)
{
indegree[temp->toE]++;
temp = temp->next;
}
}
///将入度为零的顶点入栈:
for(int i = 0; i < num; i++)
{
if(indegree[i] == 0)
{
innum.push(i);
}
}
///将入度为0的顶点从图中一一删除,并且将与该定点有关的边都删除
while(!innum.empty())
{
///删除栈顶第一个入度为0顶点
int topnum = innum.top();
innum.pop();
///删除与该点有关的所有边
Edge *temp = V[topnum].firstEdge;
while(temp)
{
indegree[temp->toE]--;
///如果和该顶点相关联的边后, 边的另一个顶点的入度为0了,则入栈
if(indegree[temp->toE] == 0)
{
innum.push(temp->toE);
}
temp = temp->next;
}
countt++;///记录删除顶点为0的顶点个数
}
///若按顺序删除入度为0的顶点个数等于原图的顶点个数, 则无环; 否则有环
if(countt == num)
return 1;
else
return 0;
}
///释放链表
void Free(int num)
{
for(int i = 0; i < num; i++)
{
Edge *p, *q, temp;
p = V[i].firstEdge;
while(p)
{
q = p->next;
free(p);
p = q;
}
V[i].firstEdge = NULL;
}
return ;
}
int main()
{
int T, edg, num, CAS = 1;
char s1[20], s2[20];
///使用map将字符串转化成数字
map<string, int> str_int;
scanf("%d", &T);
while(T--)
{
scanf("%d", &edg);
int n = edg;
num = 0;
str_int.clear();
while(n--)
{
scanf(" %s %s", s1, s2);
if(str_int.find(s1) == str_int.end())
{
str_int[s1] = num++;
}
if(str_int.find(s2) == str_int.end())
{
str_int[s2] = num++;
}
///将s2(后顶点)所对应的顶点接到s1(前顶点)所对应的顶点后面去
Edge *temp = (Edge*)malloc(sizeof(Edge));
temp->toE = str_int[s2];
temp->next = NULL;
if(V[str_int[s1]].firstEdge == NULL)///如果s1后面还没有接点,就接到后面
{
V[str_int[s1]].firstEdge = temp;
}
else///如果已经s1后面已经有边了,则找到最后接的一个点,接到它后面
{
Edge *p = V[str_int[s1]].firstEdge;
while(p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
int ans = tuopo(num);
if(ans == 1)
printf("Case %d: Yes\n", CAS++);
else
printf("Case %d: No\n", CAS++);
///释放空间
Free(num);
}
return 0;
}