題意:即找所給字符串組成的飲料名是否組成環
涉及知識:
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;
}