图——邻接表表示(C++代码)

  上学期学了数据结构,但是总是掌握不牢固,这学期的算法课给了这样一道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++实现坦克大战(新手思路)


下一篇:图的邻接表表示法