思路
并查集判环+树的直径。注意树有可能是不连通的。
树的直径通过两次bfs就能得到,具体证明见树的直径(最长路)的详细证明
真彩希帆のファン
LIS变形,本来想O(n^2)暴力踩10^8结果TLE的悲伤故事,所以学习了一下O(nlogn)的LIS求法。
对于最朴素的做法我们使用dp在n^2时间可以求出一个数列的LIS,程序如下1
2
3
4
5
6
7
8int dp[MAXN],maxs=-1;
memset(dp,1,sizeof(dp)); //假装可以这么写
for(int i=0;i<n;i++){
for(int j=0;j<i;j++){
if(dp[i]>dp[j])dp[i]=max(dp[i],dp[j]+1);
}
maxs=max(dp[i],maxs);
}
然而我们还有更机智的做法。考虑维护一个单调增的数列q[MAXN],令一个计数器cnt=0,我们从头扫到尾,然后会有两种情况:
这样就能nlogn求出数列的LIS,我们维护1-i的递增子序列长度和i-n的递减子序列长度然后处理即可。
A*算法是一种启发式搜索的算法,通过设定合理的估价函数,我们能够减少不必要的搜索从而达到减低时间复杂度的目的。当我们计算A*算法时,我们维护一个优先队列,同时按照我们规定的估价函数来进行排序。我们这样定义一个估价函数:F=G+H。这里:
F:需要排序的估价函数值
G:从起点到当前点的花费
H:我们人为设定的估价函数值
在这里我们这样理解这个估价函数,我们从起点到终点,我们定义H为当前点到终点的距离,很显然根据G+H,绕路走的F是比较大的,F就是我们人为观感上的“绕路走”,A*的估价函数的意义就是少“绕路走”,同时我们常常使用的BFS就是没有估价函数的,所以即便一些步骤我们明明知道不会产生最优解,我们依然遍历了这些步骤,A*的估价函数则避免了这个问题。
本题我们先用dijkstra计算t到每个点的距离,然后这个距离就是我们的估价函数,然后我们从s出发使用A*,然后等第k次出队列碰到t点我们输出距离。需要注意的是当s==t时k++,因为题目要求必须要走一条路。