• 【SSLOJ】最短路


    题目

    思路

    容易发现从 \(i\)\(j\) 的最优路径一定是先往右再往左。因为如果某一时刻往左走后再往右走,那么还不如在往左走的时刻直接往右走。
    所以考虑如何求出 \(dis[i][j]\) 表示只往右走,\(i\)\(j\) 的最短路。
    那么可以考虑枚举 \(j\),然后从 \(j-1\) 到 1 枚举 \(i\),容易发现走相同步数,走的越右显然更优,所以可以利用单调性求出 \(dis[i][j]\)
    然后用类似 spfa 的想法,枚举 \(i\),将 \(dis[i][j]\) 从小到大排序,向前染色。每个点最多被染色一次。
    时间复杂度 \(O(n^2)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=6010;
    int n,ans,a[N],b[N],dis[N][N],father[N];
    bool used[N];
    vector<int> pos[N];
    
    int find(int x)
    {
    	return x==father[x]?x:father[x]=find(father[x]);
    }
    
    int main()
    {
    	scanf("%d",&n);
    	for (int i=2;i<=n;i++) scanf("%d",&b[i]);
    	for (int i=2;i<=n;i++) scanf("%d",&a[i]);
    	for (register int i=1;i<=n;i++)
    	{
    		for (register int j=i-1,k=i;j>=1;j--)
    		{
    			while (a[k]>j) k--;
    			dis[j][i]=dis[k][i]+1;
    		}
    	}
    	b[1]=1;
    	for (register int i=1;i<=n;i++)
    	{
    		for (register int j=0;j<=n;j++)
    		{
    			pos[j].clear();
    			used[j]=0; father[j]=j;
    		}
    		for (int j=i;j<=n;j++)
    			pos[dis[i][j]].push_back(j);
    		for (register int j=0;j<=n;j++)
    			for (register int k=0;k<pos[j].size();k++)
    			{
    				int p=pos[j][k];
    				if (used[p]) continue;
    				used[p]=1;
    				for (int q=find(p);q>=b[p];q=find(q))
    				{
    					if (dis[i][q]>dis[i][p]+1 || (dis[i][q]==0 && i!=q)) dis[i][q]=dis[i][p]+1;
    					pos[dis[i][q]].push_back(q);
    					father[q]=find(q-1);
    				}
    			}
    	}
    	for (register int i=1;i<=n;i++)
    		for (register int j=1;j<=n;j++)
    			ans^=(i+j)*dis[i][j];
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    python的reduce()函数
    python的map()函数
    【RxJS 01】函数式编程
    【vs_dev】01 first one
    【Angular01】Angular First One ----附 ip 地址查询
    目录
    ECMA Script 6 something
    【git】打tag
    【work 0107】dione 搭建
    【nextjs】React SSR
  • 原文地址:https://www.cnblogs.com/stoorz/p/13471736.html
Copyright © 2020-2023  润新知