zoukankan      html  css  js  c++  java
  • 【u110】灾后重建

    Time Limit: 1 second
    Memory Limit: 128 MB

    【问题描述】

    B地区在地震过后,所有村庄都造成了一定的损毁,而这场地震却没对公路造成什么影响。但是在村庄重建好之前,所有与未重建完成的村
    庄的公路均无法通车。换句话说,只有连接着两个重建完成的村庄的公路才能通车,只能到达重建完成的村庄。
    给出B地区的村庄数N,村庄编号从0到N-1,和所有M条公路的长度,公路是双向的。并给出第i个村庄重建完成的时间t[i],你可以认为是同
    时开始重建并在第t[i]天重建完成,并且在当天即可通车。若t[i]为0则说明地震未对此地区造成损坏,一开始就可以通车。之后有Q个
    询问(x, y, t),对于每个询问你要回答在第t天,从村庄x到村庄y的最短路径长度为多少。如果无法找到从x村庄到y村庄的路径,经过
    若干个已重建完成的村庄,或者村庄x或村庄y在第t天仍未重建完成 ,则需要返回-1。


    【输入格式】

    输入文件rebuild.in的第一行包含两个正整数N,M,表示了村庄的数目与公路的长度。
    第二行包含N个非负整数t[0], t[1], …, t[N – 1],表示了每个村庄重建完成的时间,数据保证了t[0] ≤ t[1] ≤ … ≤ t[N – 1]。
    接下来M行,每行3个非负整数i, j, w,w为不超过10000的正整数,表示了有一条连接村庄i与村庄j的道路,长度为w,保证i≠j,且对于任
    意一对村庄只会存在一条道路。
    接下来一行也就是M+3行包含一个正整数Q,表示Q个询问。
    接下来Q行,每行3个非负整数x, y, t,询问在第t天,从村庄x到村庄y的最短路径长度为多少,数据保证了t是不下降的。

    【输出格式】

    输出文件rebuild.out包含Q行,对每一个询问(x, y, t)输出对应的答案,即在第t天,从村庄x到村庄y的最短路径长度为多少。如果在第t
    天无法找到从x村庄到y村庄的路径,经过若干个已重建完成的村庄,或者村庄x或村庄y在第t天仍未修复完成,则输出-1。

    【数据规模】

    对于30%的数据,有N≤50; 对于30%的数据,有t[i] = 0,其中有20%的数据有t[i] = 0且N>50; 对于50%的数据,有Q≤100; 对于100%的数据,有N≤200,M≤N*(N-1)/2,Q≤50000,所有输入数据涉及整数均不超过100000。

    Sample Input1

    4 5
    1 2 3 4
    0 2 1
    2 3 1
    3 1 2
    2 1 4
    0 3 5
    4
    2 0 2
    0 1 2
    0 1 3
    0 1 4
    
    
    
    

    Sample Output1

    -1
    -1
    5
    4

    【题解】

    这道题要利用floyd的原理来做。 我们floyd的3层循环如下。 for (int k=1;k<= n;k++) for (int i = 1;i <= n;i++) for (int j=1;j <= n;j++) if (w[i][j] > w[i][k]+w[k][j]) f[i][j] = w[i][k]+w[k][j]; 这里的k层循环(第一层)枚举的是经过哪一些点作为中间点来缩短i->j的距离。 可以理解为用了前k个点作为中间点来尝试更新任意两点之间的距离。 这点可以为我们所利用。 看一下我们的询问。 x,y,time 如果t[x] 或者t[y]>time则肯定是输出-1的。 对于其他的 我们可以在k层循环中的i,j循环完毕之后加上下面这些东西。 for (k=1->n) { for (i=1->n) for (j =1->n) ... 在这个位置加上我们下面所说的东西; } k层循环仍是枚举n个点。 如果t[k]<=a[now].time且t[k+1] <=a[now].time 则k可以继续枚举。表示我们可以利用k和k+1来作为中间点更新任意两点之间的距离。 如果遇到t[k]<=a[now].time且t[k+1]>a[now].time。 则表示我们最多只能用k来作为中间点更新任意两点之间的距离了。 这时我们只能尝试在利用前k个点之后输出w[x][y]了。 不能再用k+1这个点了。因为k+1这个点在a[now].time时还没有修建好。 遇到这样的k之后。now++.(a[now].time是随着now的增加递增的)。 如果now递增后t[k+1]<=a[now].time了。则可以继续利用k+1来作为中间点更新任意两点之间的距离。 怎么样?理解了吧。 然后我们把k层循环的下界改为0. 因为可能有在0时刻的询问。 这个问题在脑子里想的时候有点烦。但是写下来其实还好。 然后要先将询问存下来。 村庄从0--n-1有点麻烦。直接改成1--n,即输入的时候x,y都递增1。

    【代码】

    #include <cstdio>
    #include <cstring>
    
    struct question //用结构体把询问存下来。
    {
    	int x, y, time;
    };
    
    int n, m, t[201] = { 0 }, w[201][201], q; //t数组是各个节点修建好的时间。
    question a[50001] = { 0 };
    
    void input_data()
    {
    	memset(w, 127 / 3, sizeof(w));//一开始w数组赋值为一个很大的数字。
    	scanf("%d%d", &n, &m);
    	for (int i = 1; i <= n; i++) //输入各个节点修建好的时刻。
    		scanf("%d", &t[i]);
    	for (int i = 1; i <= m; i++) //输入边权信息。
    	{
    		int x, y, z;
    		scanf("%d%d%d", &x, &y, &z);
    		x++; y++;
    		w[x][y] = w[y][x] = z;
    	}
    	scanf("%d", &q);
    	for (int i = 1; i <= q; i++) //输入q个询问。
    	{
    		scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].time);
    		a[i].x++;
    		a[i].y++;
    	}
    }
    
    void get_ans()
    {
    	int now = 1;
    	t[n + 1] = t[n] + 10000; //这是防止上溢。
    	for (int k = 0; k <= n; k++) //k从0开始枚举
    	{
    		for (int i = 1; i <= n; i++) //以k作为中间节点尝试更新任意两点之间的距离。
    			for (int j = 1; j <= n; j++)
    				if (w[i][j] > w[i][k] + w[k][j])
    					w[i][j] = w[i][k] + w[k][j];
    		while (now <= q && t[k] <= a[now].time && t[k + 1] > a[now].time)
    		{//如果询问还没结束。且这个节点在所询问的时间内。且k+1这个节点修建的时间超过询问的时间
    			if (t[a[now].x] > a[now].time || t[a[now].y] > a[now].time)
    				printf("-1
    ");
    			else //输出依靠前k个节点作为中间节点更新出的任意两点之间的距离
    			{
    				if (w[a[now].x][a[now].y] >= w[0][0])
    					printf("-1
    ");
    				else
    					printf("%d
    ", w[a[now].x][a[now].y]);
    			}
    			now++; //看一下下一个询问是否符合要求。
    		}
    		if (now > q) //如果询问都输出了则结束。
    			break;
    	}
    }
    
    int main()
    {
    	input_data();
    	get_ans();
    	return 0;
    }



  • 相关阅读:
    CODING x 百果园 _ 水果零售龙头迈出 DevOps 体系建设第一步
    Nocalhost 亮相 CD Foundation 国内首届 Meetup,Keith Chan 将出席致辞
    做云原生时代标准化工具,实现高效云上研发工作流
    打造数字化软件工厂 —— 一站式 DevOps 平台全景解读
    WePack —— 助力企业渐进式 DevOps 转型
    CODING Compass —— 打造行云流水般的软件工厂
    Nocalhost —— 让云原生开发回归原始而又简单
    CODING 代码资产安全系列之 —— 构建全链路安全能力,守护代码资产安全
    Nocalhost:云原生开发新体验
    使用 Nocalhost 开发 Kubernetes 中的 APISIX Ingress Controller
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7632313.html
Copyright © 2011-2022 走看看