• ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TSH OJ-旅行商TSP)


    做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -||


    旅行商(TSP)


    描述

    Shrek是一个大山里的邮递员,每天负责给所在地区的n个村庄派发信件。但杯具的是,由于道路狭窄,年久失修,村庄间的道路都只能单向通过,甚至有些村庄无法从任意一个村庄到达。这样我们只能希望尽可能多的村庄可以收到投递的信件。

    Shrek希望知道如何选定一个村庄A作为起点(我们将他空投到该村庄),依次经过尽可能多的村庄,路途中的每个村庄都经过仅一次,最终到达终点村庄B,完成整个送信过程。这个任务交给你来完成。

    输入

    第一行包括两个整数n,m,分别表示村庄的个数以及可以通行的道路的数目。

    以下共m行,每行用两个整数v1和v2表示一条道路,两个整数分别为道路连接的村庄号,道路的方向为从v1至v2,n个村庄编号为[1, n]。

    输出

    输出一个数字,表示符合条件的最长道路经过的村庄数。

    Example

    Input

    4 3
    1 4
    2 4
    4 3
    

    Output

    3
    

    限制

    1 ≤ n ≤ 1,000,000

    0 ≤ m ≤ 1,000,000

    输入保证道路之间没有形成环

    时间:2 sec

    空间:256 MB

    提示

    拓扑排序


      手记部分:

      刚开始做这道题的时候,我不知道有拓扑排序,一直在想结点10^6的图该怎么操作,所以第一个想法就是邻接表,用一个Vetor和一个数组模拟邻接表,之后考虑到在单向寻找最长路的时候应该怎样做优化。最开始的想法是深度优先搜索(DFS),甚至考虑了广度优先搜索(BFS),但是无论怎样都需要O(n^2)的时间度,无疑要么考虑优化,要么改变算法,然后猛然间发现题目下面的提示-拓扑排序- -||,博主顿时觉得脑残了~

      然后博主开始找拓扑排序相关资料,还好有本学长借我的一本图论书,看完概念后理解了AOV和AOE网络以及拓扑排序的基本概念,但对这道题我还是有点迷糊,因为直接排序无疑会破坏邻接表,后来才想到用数组存放拓扑排序后的下标,后来发现这个数组其实就是一种队列,这样就不会破坏编号顺序和邻接表。之后准备开始写主算法的时候原来考虑的是用DFS+优化,后来突然发现每座城市经拓扑排序后,有一种状态满足无后效性——从起始城市到此城市所经过的最大城市数。

      有了这个想法之后就在拓扑排序的基础上(具体算法写在了拓扑排序函数内),完成了DP算法。

      因此这道题目,我的方法就是邻接表(图的保存和查找)+队列(保存拓扑排序)+DP(时间优化)+拓扑排序(完成AOV网络的结点排序)


      以上为博主胡言乱语= =||,直接看懂代码比较容易懂。

      

      

     1 //TshingHua OJ 旅行商(TSP)
     2 //邻接表+DP+队列+拓扑排序
     3 //Memory:66304KB Time:1101Ms(No.17)
     4 #include<iostream>
     5 #include<cstring>
     6 #include<cstdio>
     7 using namespace std;
     8 
     9 #define MAX 1000005
    10 #define Max(x,y) ((x)>(y)?(x):(y))
    11 
    12 int n, m;    //村庄个数-道路数
    13 int topology[MAX],lt;    //拓扑数组-长度
    14 int mark[MAX];    //入度标记
    15 int maxCity = 1;    //答案
    16 
    17 //从City通向的村庄
    18 struct Node{
    19     int num;    //村庄编号
    20     Node *next;
    21     Node(){ next = NULL; }
    22     Node(int x,Node *n) :num(x),next(n){}
    23 };
    24 
    25 struct City{
    26     Node *nc;    //next-city
    27     int dp;        //至此可通过的最大城市数
    28     City(){ nc = NULL; dp = 1; }
    29     void insert(int nc);
    30 }city[MAX];
    31 
    32 void City::insert(int nc)
    33 {
    34     mark[nc]++;    //直接后继城市入度+1
    35     if (this->nc == NULL)
    36         this->nc = new Node(nc,NULL);
    37     else{
    38         Node *node = new Node(nc,this->nc);
    39         this->nc = node;
    40     }
    41     return;
    42 }
    43 
    44 /*拓扑排序*/
    45 void Topology()
    46 {
    47     for (int i = 1; i <= n; i++)
    48         if (!mark[i]) topology[++lt] = i;    //入度为0的city
    49     //Main Content
    50     for (int i = 1; topology[i];i++)
    51     {
    52         int cur = topology[i];    //该city-number
    53         //遍历该city所有直接后继
    54         for (Node *tmp = city[cur].nc; tmp != NULL; tmp = tmp->next)
    55         {
    56             //此处满足无后效性-DP
    57             city[tmp->num].dp = Max(city[cur].dp + 1, city[tmp->num].dp);
    58             maxCity = Max(city[tmp->num].dp, maxCity);
    59             //处理后继
    60             int num = tmp->num;
    61             mark[num]--;    //后继入度-1
    62             if (!mark[num])    topology[++lt] = num;    //若后继入度为0
    63         }
    64     }
    65 }
    66 
    67 int main()
    68 {
    69     scanf("%d%d", &n, &m);
    70     for (int i = 0; i < m; i++)
    71     {
    72         int x, y;    //x->y
    73         scanf("%d%d", &x, &y);
    74         city[x].insert(y);
    75     }
    76     /*拓扑排序*/
    77     Topology();
    78     printf("%d
    ", maxCity);
    79 
    80     return 0;
    81 }
    小墨 - - 原创

    他坐在湖边,望向天空,她坐在对岸,盯着湖面
  • 相关阅读:
    Sql Server 跨服务器连接
    ASCII码与16进制的互相转换(表)
    c#多线程 Invoke方法的使用
    登陆时验证码的制作(asp.net)
    jQ&js给label
    IT行业的一些专业术语
    html div 加边框样式
    分布式技术 memcached
    分布式技术 webservice
    MVC 绑定 下拉框数据
  • 原文地址:https://www.cnblogs.com/Inkblots/p/4994588.html
Copyright © 2020-2023  润新知