zoukankan      html  css  js  c++  java
  • 【CF1528D】It's a bird! No, it's a plane! No, it's AaParsa!

    题目

    题目链接:https://codeforces.com/contest/1528/problem/D
    一张 (n) 个点 (m) 条边的有向图,第 (i) 条边为 ((u_i,v_i,d_i))。每一秒所有边到达的点的编号都会加一,也就是第 (c) 秒时,第 (i) 条边会变为 ((u_i,(v_i+c)mod n,d_i))
    求全源最短路。注意可以在任意点停留任意时间。
    (nleq 600;mleq n^2),保证每一个点都有出边。

    思路

    显然难点就在于可以在可以停留,否则直接跑 dijkstra 即可。
    考虑在原图中增加 (n) 条边,其中第 (i) 条为 ((i,(i+1)mod n,1)),这样有一个非常妙的地方:假设我们要在 (u)(c) 秒,然后去到 (v),那么等价于这一个时刻直接从 (u) 去到 (v-c),然后不断走新的边 (c) 次到达 (u)
    除了第一步不能走新建的边之外,其他时刻都可以任意走,因为走一次新建的边等价于在上一次走原图的时刻多等一秒。
    那么直接枚举所有源点,然后新建一个点 (S) 把这一个点除了新加的路径以外所有路径 copy 过去,然后正常跑 dijkstra 即可。
    时间复杂度 (O(n^3))。注意因为边数是 (O(n^2)) 的,所以不要采用堆优化 dijkstra。否则将会退化成 (O(nmlog n))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    const int N=610,M=400010;
    int n,m,tot,tot1,head[N];
    bool vis[N];
    ll dis[N];
    
    struct edge
    {
    	int next,to,dis;
    }e[M];
    
    void add(int from,int to,int dis)
    {
    	e[++tot]=(edge){head[from],to,dis};
    	head[from]=tot;
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	scanf("%d%d",&n,&m);
    	for (int i=1,x,y,z;i<=m;i++)
    	{
    		scanf("%d%d%d",&x,&y,&z);
    		add(x+1,y+1,z);
    	}
    	tot1=tot;
    	for (int i=1;i<=n;i++)
    	{
    		memset(vis,0,sizeof(vis));
    		memset(dis,0x3f3f3f3f,sizeof(dis));
    		head[n+1]=-1; dis[n+1]=0; tot=tot1;
    		for (int j=head[i];~j;j=e[j].next)
    			add(n+1,e[j].to,e[j].dis);
    		for (int j=1;j<=n;j++)
    		{
    			int k=0;
    			for (int l=1;l<=n+1;l++)
    				if (!vis[l] && (!k || dis[l]<dis[k])) k=l;
    			vis[k]=1;
    			for (int l=head[k];~l;l=e[l].next)
    			{
    				int v=(e[l].to+dis[k]-1)%n+1;
    				dis[v]=min(dis[v],dis[k]+e[l].dis);
    			}
    			if (k<=n) dis[k%n+1]=min(dis[k%n+1],dis[k]+1);
    		}
    		dis[i]=0;
    		for (int j=1;j<=n;j++) cout<<dis[j]<<' ';
    		printf("
    ");
    	}
    	return 0;
    }
    
  • 相关阅读:
    在python3.7下怎么安装matplotlib与numpy
    kNN(从文本文件中解析数据)
    k-近邻算法(kNN)笔记
    第二章--k-近邻算法(kNN)
    C++学习笔记一 —— 两个类文件互相引用的处理情况
    (转) C++中基类和派生类之间的同名函数的重载问题
    初试 Matlab 之去除水印
    (转) linux之sort用法
    vim 简单配置
    hdu 5358 First One
  • 原文地址:https://www.cnblogs.com/stoorz/p/14808232.html
Copyright © 2011-2022 走看看