light oj 1003—拓撲排序

題意:即找所給字符串組成的飲料名是否組成環

涉及知識:

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章