1. 程式人生 > >圖——鄰接表表示(C++代碼)

圖——鄰接表表示(C++代碼)

16px other ats 存儲 一個 不可 groups 初始 create

  上學期學了數據結構,但是總是掌握不牢固,這學期的算法課給了這樣一道OJ題目

描述:

There is a group of people playing table tennis, each person can only play with the others once.

The rules of the game are as follows:

If A beats B, and B beats C, and there is no competition between A and C, then A beats C.

If A beats B, B beats C, and C beats A, then no one is champion.

Your task is to figure out whether there is a champion.

Input

Each test case contains several groups. One group begins with an integer n(n<1000), followed by n lines. Each line has a pair of names (separated by space), which means the first one beats the second one. If n is 0, the input ends.

Output

If there is a winner, print "Yes", else print "No".

示例測試集:

- 第1組

輸入:

2
qRj dIm
aTy oFu
4
qRj aTy
qRj oFu
oFu cLq
aTy qUr
0

輸出:

No
Yes


這道題明顯是用圖論的知識,我的解題思路如下,通過每次輸入構建一個有向圖,然後通過判斷
1.圖中入度為0的頂點,當且僅當存在一個入度為0的頂點才可能有winner
2.圖是否有環,如果存在環,則肯定不可能有winner
3.個人認為第二點太過絕對,例如a b b c c d d a 我覺得這組數據中是有勝利者d的但是通過試驗,測試點中並沒有考慮這種情況,故我也不考慮了

具體代碼如下
#include <iostream>
#include<string>
#include<stack>
#define MAXVERTEX 10000   //最大頂點數
using namespace std;
int indegree[MAXVERTEX];

typedef string vertextype;    //定義頂點的存儲類型

typedef struct ArcNode  //邊表節點
{
    int adjvex; //鄰接點域,存儲該頂點對應的下標
    struct ArcNode *next; //鏈域,指向下一個鄰接點
}ArcNode;

typedef struct VertexNode   //頂點表節點
{
    vertextype data;    //存儲頂點數據的信息
    ArcNode *firstarc;  //邊表頭指針
}AdjList[MAXVERTEX];

typedef struct
{
    AdjList adjlist;    //定義鄰接表
    int numvertex;  //當前鄰接表的頂點數
    int numarc; //當前鄰接表的邊數
}GraphAdjList;

//判斷x是不是G中的節點
bool ExitInGraph(GraphAdjList &G, VertexNode x) {
    for (int i = 0; i < G.numvertex; i++) {
        if (G.adjlist[i].data == x.data)
            return true;
    }
    return false;
}

//把G中節點x,y連接起來
void Connect(GraphAdjList &G, VertexNode x, VertexNode y) {
    int xindex, yindex;
    for (int i = 0; i < G.numvertex; i++) {
        if (G.adjlist[i].data == y.data)
            yindex = i;
        if (G.adjlist[i].data == x.data)
            xindex = i;
    }
    ArcNode *e = new ArcNode;
    e->adjvex = yindex;
    e->next = G.adjlist[xindex].firstarc;
    G.adjlist[xindex].firstarc = e;
}

//尋找當前節點在G中的index
int FindeIndex(GraphAdjList &G, VertexNode x) {
    int xindex;
    for (int i = 0; i < G.numvertex; i++) {
        if (G.adjlist[i].data == x.data)
            return i;
    }
}

//建立圖的鄰接表
void CreateAdjListGraph(GraphAdjList &G, int num)
{
    ArcNode *e;
    G.numarc = num;      //輸入當前圖的邊數
    G.numvertex = 0;      //初始圖的節點數為0
    for (int i = 0, j = 0; i < G.numarc; i++)    //建立頂點表,j用來表示當前頭結點的index
    {
        string a, b;
        cin >> a >> b;
        VertexNode x, y;
        x.data = a, y.data = b;
        if (ExitInGraph(G, x) && ExitInGraph(G, y)) {
            Connect(G, x, y);
        }
        else if (!ExitInGraph(G, x) && ExitInGraph(G, y)) {
            e = new ArcNode;
            G.adjlist[j].data = x.data;     //給當前節點賦值data
            e->adjvex = FindeIndex(G, y);   //給e賦值 
            e->next = NULL;
            G.adjlist[j].firstarc = e;

            j++;
            G.numvertex++;
        }
        else if (ExitInGraph(G, x) && !ExitInGraph(G, y)) {
            e = new ArcNode;
            G.adjlist[j].data = y.data;
            G.adjlist[j].firstarc = NULL;
            e->adjvex = j;
            int xindex = FindeIndex(G, x);
            e->next = G.adjlist[xindex].firstarc;
            G.adjlist[xindex].firstarc = e;
            j++;
            G.numvertex++;
        }
        else {
            e = new ArcNode;

            G.adjlist[j].data = x.data;
            G.adjlist[++j].data = y.data;
            G.adjlist[j].firstarc = NULL;

            e->adjvex = j;
            e->next = NULL;

            G.adjlist[j - 1].firstarc = e;

            G.numvertex += 2;
            j++;
        }

    }

}

void FindInDegree(GraphAdjList &g, int indegree[])
{                                     //求每個頂點的入度
    int i;
    ArcNode *p;
    for (i = 0; i<g.numvertex; i++)
        indegree[i] = 0;
    for (i = 0; i<g.numvertex; i++)
    {
        p = g.adjlist[i].firstarc;
        while (p)
        {
            indegree[p->adjvex]++;
            p = p->next;
        }
    }
}
bool TopologicalSort(GraphAdjList &g)  //判斷圖中是否存在回路 存在 返回 true
{
    for (int i = 0; i<g.numvertex; i++)
        indegree[i] = 0;
    int count;
    int k, i;
    ArcNode *p;
    stack<int>s;
    FindInDegree(g, indegree);   //對各頂點求入度
    for (i = 0; i<g.numvertex; i++)  //將入度為0的頂點壓入棧
        if (!indegree[i])
        {
            s.push(i);
            //visited[i] = 1;
        }
    //if (s.size() != 1)return true;//不能擁有兩個入讀為0 的點
    count = 0;
    while (!s.empty())
    {
        i = s.top();
        s.pop();
        cout<<g.adjlist[i].data <<" ";   //輸出拓撲排序序列
        count++;
        for (p = g.adjlist[i].firstarc; p; p = p->next)
        {
            k = p->adjvex;
            //visited[k] = 1;
            if (!(--indegree[k]))
                s.push(k);
        }
    }

    if ((count == g.numvertex))
    {
        return false;//這就說明沒有環
    }
    else
        return true;
    //printf("\n該圖有回路\n");
}

int main()
{
    int n;
    while (cin >> n, n) {
        GraphAdjList G;
        CreateAdjListGraph(G, n);
        if (TopologicalSort(G))
            cout << "No" << endl;
        else
            cout << "Yes" << endl;
        n = 0;
    }
    //system("pause");
    return 0;
}

代碼不完善,還請多多原諒

圖——鄰接表表示(C++代碼)