旅行商(TSP)->(拓扑排序)

旅行商(TSP)


Description

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.

Input

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

Output maximum number of villages Shrek can pass by.

Example

Input

4 3
1 4
2 4
4 3

Output

3

Restrictions

1 <= n <= 1,000,000

0 <= m <= 1,000,000

These is no loop road in the input.

Time: 2 sec

Memory: 256 MB

Hints

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

提示

拓扑排序

本来做这题是毫无思路的,后来看到了题下的提示说要用拓扑排序

然后思路就清晰了许多,写完debug了半天才想起来这OJ无法使用

C++容器,于是乖乖查了题解。

具体算法仍是拓扑排序的传统做法:

找到入度为0的点作为起点,依次处理后继,

唯一的不同是需要保存到达该城市的当前最大值。

然后更新答案即可

#include<stdio.h>
using namespace std;
#define maxn 1000005
int MAX(int a,int b)
{
	if(a<b)
		return b;
	return a;
}
int n,m,cnt,q[maxn],degree[maxn];
//q为拓扑数组---cnt为其长度
//degree为各点入度
//n,m分别为点数和边数
int ans=1;//保存答案
struct node
{
	int num;//村庄编号
	node *next;
	node()
	{
		next=NULL;
	}
	node(int x,node *n) :num(x),next(n){}
};
//该OJ无法使用C++容器,因此
//只能现学自认为重定义(看了题解)
struct city
{
	node *nc;//next-city
	int dp;//至此所通过的最大城市数
	city(){nc=NULL;dp=1;}
	void insert(int nc);
}a[maxn];
void city::insert(int nc)
{
	degree[nc]++;
	if(this->nc==NULL)
		this->nc=new node(nc,NULL);
	else
	{
		node *nodes=new node(nc,this->nc);
		this->nc=nodes;
	}
	return;
}
void Topology()
{
	for(int i=1;i<=n;i++)
		if(!degree[i])
			q[++cnt]=i;
	for(int i=1;q[i];i++)
	{
		int res=q[i];
		for(node *tmp=a[res].nc;tmp!=NULL;tmp=tmp->next)
		{
			a[tmp->num].dp=MAX(a[res].dp+1,a[tmp->num].dp);
			ans=MAX(ans,a[tmp->num].dp);
			//处理后继
			int x=tmp->num;
			degree[x]--;
			if(!degree[x])
				q[++cnt]=x;
		}
	}
}
int  main()
{
	scanf("%d%d",&n,&m);
	for(int i=0;i<m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		a[x].insert(y);
	}
	Topology();
	printf("%d\n",ans);
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值