fold的毒瘤题(easy)

1 篇文章 0 订阅

fold的毒瘤题(easy)

TimeLimit:1000MS  MemoryLimit:256MB
64-bit integer IO format: %lld
Problem Description

给出一幅有n(≤50)个点, m(≤500)条边的无向图. 保证任意2点间都至少存在一条路径可以连通, 每条边上都有一个权值Vi(≤500)

不幸的是, 这m条边都被损坏了.

fold打算修复其中一些边让一些点连通, 不过, fold并不打算让全部的点连通, 而是选择一些编号特殊的点让它们连通.

fold有q(≤50)次询问, 对于每次询问, 他会选择所有编号在[l,r]之间, 并且编号%p=c的点(保证至少存在2个这样的点), 让这些特殊点连通(任意两个特殊点之间至少存在一条路径).

这里有很多种修复方案, 每种修复方案中都有权值最大的边, fold希望找到这么多方案中: 边权最大值最小的一个方案

你能帮助fold计算出每次询问的最小值是多少吗?

这里询问是独立的, 也就是上一个询问里的修复计划并没有付诸行动.


点的编号从1开始


Input

第一行三个正整数n. m. q, 含义如题面所述
接下来m行, 每行三个正整数Xi、Yi、Vi, 表示一条连接Xi和Yi的双向道路, 权值是Vi (1≤Vi<≤500). 可能有自环, 可能有重边.
接下来Q行, 每行四个正整数Li、Ri、Pi、Ci, 表示这次询问的点是[Li,Ri](1≤Li<Ri≤n)区间中所有编号%Pi(1≤Pi<n)=Ci(0≤Ci<Pi)的点. (保证参与询问的特殊点至少有两个)

Output

输出q行, 每行一个正整数表示对应询问的答案.

SampleInput
5 5 2
1 2 5
5 1 5
3 1 1
4 2 9
1 1 5
1 4 1 0
2 3 1 0
SampleOutput
9
5

思路:典型的青蛙跳问题,求每条路径的的最长边然后曲最小值,使用floyd算法,代码如下

#include<stdio.h>  
#include<algorithm>  
#define MAX_V 1000 //注意大小   
#define INF 999999999   
using namespace std;  
  
int d[MAX_V][MAX_V];  
int V;   //注意赋值   
  
void floyd(){  
    for(int k = 1; k <= V; k++){     
        for(int i = 1; i <= V; i++){  
            for(int j = 1; j <= V; j++){  
                d[i][j] = min(d[i][j], max(d[i][k] , d[k][j]));  //minmax求两点之间的最长边的最小值  
            }  
        }  
    }  
}  
int main(){  
    int n,m,q,i,x,y,z,p,c,l,r,cnt,ans;  
    int a[MAX_V];  
    scanf("%d%d%d",&n,&m,&q);  
    V=n;  
    for(i=0;i<=n;i++){  
        for(int j=0;j<=n;j++){  
            d[i][j]=INF;  
        }  
    }  
    for(i=0;i<m;i++){   //注意是m条边,比赛时写错  
        scanf("%d%d%d",&x,&y,&z);  
        if(d[x][y]>z){  
            d[x][y]=z;  
            d[y][x]=z;  
        }  
          
    }  
    floyd();  
    for(i=0;i<q;i++){  
        scanf("%d%d%d%d",&l,&r,&p,&c);  
        cnt=0;  
        ans=0;  
        for(int j=l;j<=r;j++){  
            if(j%p==c){  
                a[cnt++]=j;  //记录满足条件的点  
            }  
        }  
        for(int j=0;j<cnt;j++){  
            for(int k=j+1;k<cnt;k++){  
                ans=max(d[a[j]][a[k]],ans);    
            }     
        }  
        printf("%d\n",ans);  
    }  
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值