标签:
做这道题感觉异常激动,因为在下第一次接触拓扑排序啊= =,而且看了看解释,猛然发现此题可以用DP优化,然后一次A掉所有样例,整个人激动坏了,哇咔咔咔咔咔咔咔~ 咔咔~哎呀,笑岔了- -||
Shrek is a postman working in the mountain, whose routine work is sending mail to n villages. Unfortunately, road between villages is out of repair for long time, such that some road is one-way road. There are even some villages that can’t be reached from any other village. In such a case, we only hope as many villages can receive mails as possible.
Shrek hopes to choose a village A as starting point (He will be air-dropped to this location), then pass by as many villages as possible. Finally, Shrek will arrived at village B. In the travelling process, each villages is only passed by once. You should help Shrek to design the travel route.
There are 2 integers, n and m, in first line. Stand for number of village and number of road respectively.
In the following m line, m road is given by identity of villages on two terminals. From v1 to v2. The identity of village is in range [1, n].
Output maximum number of villages Shrek can pass by.
Input
4 3
1 4
2 4
4 3
Output
3
1 <= n <= 1,000,000
0 <= m <= 1,000,000
These is no loop road in the input.
Time: 2 sec
Memory: 256 MB
Topological sorting
Shrek是一个大山里的邮递员,每天负责给所在地区的n个村庄派发信件。但杯具的是,由于道路狭窄,年久失修,村庄间的道路都只能单向通过,甚至有些村庄无法从任意一个村庄到达。这样我们只能希望尽可能多的村庄可以收到投递的信件。
Shrek希望知道如何选定一个村庄A作为起点(我们将他空投到该村庄),依次经过尽可能多的村庄,路途中的每个村庄都经过仅一次,最终到达终点村庄B,完成整个送信过程。这个任务交给你来完成。
第一行包括两个整数n,m,分别表示村庄的个数以及可以通行的道路的数目。
以下共m行,每行用两个整数v1和v2表示一条道路,两个整数分别为道路连接的村庄号,道路的方向为从v1至v2,n个村庄编号为[1, n]。
输出一个数字,表示符合条件的最长道路经过的村庄数。
见英文题面
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\n", maxCity); 79 80 return 0; 81 }
ACM/ICPC 之 数据结构-邻接表+DP+队列+拓扑排序(TshingHua OJ-旅行商TSP)
标签:
原文地址:http://www.cnblogs.com/Inkblots/p/4994588.html