码迷,mamicode.com
首页 > 其他好文 > 详细

TSP 旅行商

时间:2018-12-31 13:51:38      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:题目   printf   node   main   fir   方便   col   return   模板   

THUOJ 数据结构(上)TSP 旅行商


实现思路

建立邻接表

  • 每读入一条边u->v,将其插入u中(后面将实现的tspNode中的边,是以其为出发点的边),并将v的入度+1

    拓扑排序过程中计算最长道路经过的村庄数

  • 算法:零入度拓扑排序,p166 of 数据结构(c++语言版)_邓俊辉
  1. 扫描所有节点,入度为0的入栈
  2. 从栈顶开始,每读一个节点a,扫描其边,相连节点b入度-1,ind变为0的入栈;
    更新b‘路径长度=max(a‘s+1,b‘);更新max路径;

    边界情况处理

  • 由题意
    1 ≤ n ≤ 1,000,000
    0 ≤ m ≤ 1,000,000
    主要边界情况为:路径数量m=0时,此时应该输出1

面向对象

  • 以往做oj题时,只追求运行效率和代码简洁,未按照面向对象思维开发,得不偿失,此次首次尝试面向对象,让我们注重培养计算思维和抽象思维能力吧

    1.实现堆栈模板类stack

ADT
#define DEFAULT_CAPACITY 10
template <typename T>
class stack
{
  private:
    T *st;
    int capacity;
    int top;
    void expand();//未真正实现,集成在了push中
  public:
    //构造函数
    stack(int c = DEFAULT_CAPACITY)//实例化一个容量为c的堆栈
    //析构函数
    ~stack() { delete[] st; }
    int getsize() const { return top; }//top恰为元素个数
    bool empty() { return top == 0; }
    void push(T a);
    T pop();
};

2.tsp节点的ADT

//边表结点
struct edgeNode
{
    int adjvex; // 邻接点域
    struct edgeNode *next;
};

//TSP节点
template <typename T>
class tspNode
{
  public:
    int ind, road;                       //为了方便把ind定义为public了
    void inserte(int i);                 //insert edge 插入指向节点i的边
    int indegree() const { return ind; } //读取入度
    int outdegree() const { return outd; }
    edgeNode *getfirstedge() { return firstedge; }
    //构造函数
    tspNode()
    {
        ind = 0;
        outd = 0;
        road = 1;
        firstedge = NULL;
    }

  private:
    int outd; //outdegree
    edgeNode *firstedge;
};
  • 像数组一样使用模板类
    tspNode<int> *tsp = new tspNode<int>[n + 1];
    delete[] tsp;
    //或形如 tspNode<int> tsp[10];

源代码

tsp.cpp
#include <cstdio>
#include "tsp.h"
const int stackSize = 1000;
int main()
{
    int n, m;

    scanf("%d %d", &n, &m);
    if (m == 0)
    {
        printf("%d\n", 1);
        return 0;
    }
    tspNode<int> *tsp = new tspNode<int>[n + 1];
    int u, v;
    for (int i = 0; i < m; i++)
    {
        scanf("%d", &u);
        scanf("%d", &v); //u->v
        tsp[u].inserte(v);
        tsp[v].ind++;
    } //初始化
    stack<int> stack(stackSize);
    for (int i = 1; i <= n; i++)
    {
        if (tsp[i].indegree() == 0)
            stack.push(i); //遇到入度为0的,将其秩入栈
    }
    int a = 0, b = 0, maxroad = 0;
    edgeNode *p;
    while (!stack.empty())
    {
        a = stack.pop();
        p = tsp[a].getfirstedge();
        while (p != NULL)
        {
            b = p->adjvex;
            tsp[b].ind--;
            if (tsp[b].road < 1 + tsp[a].road)
            {
                tsp[b].road = 1 + tsp[a].road;
            }
            if (maxroad < tsp[b].road)
                maxroad = tsp[b].road;
            if ((tsp[b].ind) == 0)
                stack.push(b);
            p = p->next;
        }
        //从栈顶开始,每读一个节点a,扫描其边,相连节点b入度-1,b‘路径长度=max(a‘s+1,b‘)并更新max路,ind变为0的入栈,
    }
    printf("%d\n", maxroad);
    delete[] tsp;
    return 0;
}

tsp.h
#include <cstdio>

//边表结点
struct edgeNode
{
    int adjvex; // 邻接点域
    struct edgeNode *next;
};

//TSP节点
template <typename T>
class tspNode
{
  public:
    int ind, road;                       //为了方便把ind定义为public了
    void inserte(int i);                 //insert edge 插入指向节点i的边
    int indegree() const { return ind; } //读取入度
    int outdegree() const { return outd; }
    edgeNode *getfirstedge() { return firstedge; }

    tspNode()
    {
        ind = 0;
        outd = 0;
        road = 1;
        firstedge = NULL;
    }

  private:
    int outd; //outdegree
    edgeNode *firstedge;
};

template <typename T>
void tspNode<T>::inserte(int e)
{
    edgeNode *s = new edgeNode;
    s->adjvex = e;
    s->next = firstedge;
    firstedge = s;
    outd++;
};

#define DEFAULT_CAPACITY 10
template <typename T>
class stack
{
  private:
    T *st;
    int capacity;
    int top;
    void expand();

  public:
    stack(int c = DEFAULT_CAPACITY)
    {
        st = new T[capacity = c];
        top = 0;
    }
    ~stack() { delete[] st; }
    int getsize() const { return top; }
    bool empty() { return top == 0; }
    void push(T a)
    {
        st[top++] = a;
        if (top == capacity)
        {
            T *oldst = st;
            st = new T[capacity <<= 1];
            for (int i = 0; i < top; i++)
                st[i] = oldst[i];
            delete[] oldst;
        }
    }
    T pop() { return st[--top]; }
};

复杂度分析

  • 邻接表初始化:O(m)
  • 拓扑排序:扫描入度为0的点O(n)
  • 零入度算法:单次操作相当于删除一条边,O(m)
  • 堆栈扩容:分摊不过O(1),总共不过O(n)
  • 结论:时间复杂度O(m+n),空间消耗为邻接表和堆栈,也为O(m+n)

TSP 旅行商

标签:题目   printf   node   main   fir   方便   col   return   模板   

原文地址:https://www.cnblogs.com/yhjd/p/10201809.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!