zoukankan      html  css  js  c++  java
  • [洛谷P1119][codevs1817]灾后重建

    题目大意:有n个村庄和一些连通两个村庄的双向道路。每个村庄在一个特定的时间修复。没有修复的村庄不能经过。现在有一系列询问,问两个村庄在t时刻的最短路(如果无法到达或两个村庄本身未修复,输出-1)。

    解题思路:村庄数量少,可以考虑floyd。

    但询问与时间有关,不同时间内最短路是不同的,那么对每个询问都跑一遍最短路?$O(qn^3)$的时间复杂度一定会超时。

    不过我们可以发现,如果t1~t2时间段内,没有任何修改,就不必每次跑一遍最短路。

    而且,floyd第一重循环是枚举中间点的,那我们按照修复时间从小到大枚举中间点,然后进行后两重循环,就能保证此次循环后的状态是修复了这个村庄后,而后面的村庄还未修复时的状态。

    然后在这中间处理询问即可。

    这样做相当于只跑了一遍floyd就处理完了询问,所以总时间复杂度$O(q+n^3)$,即可通过此题。

    C++ Code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cctype>
    using namespace std;
    int n,m,dis[202][202],tm[202];
    struct sj{
    	int t,num;
    	bool operator<(const sj& rhs)const{return t<rhs.t;}
    }p[202];
    inline int readint(){
    	char c=getchar();
    	for(;!isdigit(c);c=getchar());
    	int d=0;
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    int main(){
    	n=readint(),m=readint();
    	for(int i=0;i<n;++i)
    	p[i]=(sj){tm[i]=readint(),i};
    	sort(p,p+n);
    	memset(dis,0x3f,sizeof dis);
    	while(m--){
    		int x=readint(),y=readint(),z=readint();
    		dis[x][y]=dis[y][x]=z;
    	}
    	m=readint();
    	int now=1,x=readint(),y=readint(),t=readint();
    	p[n].t=0x3f3f3f3f;
    	for(int f=0;;++f){
    		int k=p[f].num;
    		while(p[f].t>t){
    			if(tm[x]>t||tm[y]>t||dis[x][y]==0x3f3f3f3f)puts("-1");else
    			printf("%d
    ",dis[x][y]);
    			if(++now>m)return 0;
    			x=readint(),y=readint(),t=readint();
    		}
    		if(f==n)return 0;
    		for(int i=0;i<n;++i)
    		if(i!=k)
    		for(int j=0;j<n;++j)
    		if(i!=j&&j!=k&&dis[i][j]>dis[i][k]+dis[k][j])
    		dis[i][j]=dis[i][k]+dis[k][j];
    	}
    	return 0;
    }
    

    由于洛谷支持Java了,我又写了个Java的代码,比较丑陋,而且时间也极慢。但还是能过去的。

    Java Code:

    import java.io.*;
    import java.util.*;
    public class Main{
        public static void main(String[] args)throws IOException{
            StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
            PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
            in.nextToken();
            int n=(int)in.nval,m,tm[]=new int[202],tm2[]=new int[202],dis[][]=new int[202][202],nb[]=new int[202];
            in.nextToken();
            m=(int)in.nval;
            for(int i=0;i<n;++i)
            for(int j=0;j<n;++j)dis[i][j]=0x3f3f3f3f;
            for(int i=0;i<n;++i){
                in.nextToken();
                tm[i]=tm2[i]=(int)in.nval;
                nb[i]=i;
            }
            for(int i=0;i<n;++i)
            for(int j=i+1;j+1<n;++j)
            if(tm[i]>tm[j]){
                int t=tm[i];
                tm[i]=tm[j];
                tm[j]=t;
                t=nb[i];
                nb[i]=nb[j];
                nb[j]=t;
            }
            while(m!=0){
                --m;
                int x,y,z;
                in.nextToken();
                x=(int)in.nval;
                in.nextToken();
                y=(int)in.nval;
                in.nextToken();
                z=(int)in.nval;
                dis[x][y]=dis[y][x]=z;
            }
            in.nextToken();
            m=(int)in.nval;
            int x,y,t,now=1;
            in.nextToken();x=(int)in.nval;
            in.nextToken();y=(int)in.nval;
            in.nextToken();t=(int)in.nval;
            tm[n]=0x3f3f3f3f;
            for(int p=0;;++p){
                int k=nb[p];
                while(tm[p]>t){
                    if(tm2[x]>t||tm2[y]>t||dis[x][y]==0x3f3f3f3f)
                    out.println(-1);else
                    out.println(dis[x][y]);
                    ++now;
                    if(now>m){
                        out.close();
                        return;
                    }
                    in.nextToken();x=(int)in.nval;
                    in.nextToken();y=(int)in.nval;
                    in.nextToken();t=(int)in.nval;
                }
                if(p==n)break;
                for(int i=0;i<n;++i)
                if(i!=k)
                for(int j=0;j<n;++j)
                if(i!=j&&j!=k&&dis[i][j]>dis[i][k]+dis[k][j])
                dis[i][j]=dis[i][k]+dis[k][j];
            }
            out.close();
        }
    }
    
  • 相关阅读:
    开通博客
    实验一、命令解释程序的编写实验
    C#题目
    将Textbox、listview控件里的数据导入Excel
    unpV1的源码的使用方法
    git的基本使用方法(备忘)
    Shell中的exec和source解析(转载)
    无限式查找2013年2月28日
    解决"wxPython在Mac下的64位支持"的问题
    寻找固定的和2013年2月26日
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/7761075.html
Copyright © 2011-2022 走看看