环境治理、染色时间、小蓝组网

环境治理

环境治理

问题描述

LQ 国拥有 nn 个城市, 从 0 到 n−1n−1 编号, 这 nn 个城市两两之间都有且仅有 一条双向道路连接, 这意味着任意两个城市之间都是可达的。每条道路都有一 个属性 DD, 表示这条道路的灰尘度。当从一个城市 AA 前往另一个城市 BB 时, 可 能存在多条路线, 每条路线的灰尘度定义为这条路线所经过的所有道路的灰尘 度之和, LQ 国的人都很讨厌灰尘, 所以他们总会优先选择灰尘度最小的路线。

LQ 国很看重居民的出行环境, 他们用一个指标 PP 来衡量 LQ 国的出行环 境, PP 定义为:

P=∑i=0n−1∑j=0n−1d(i,j)P=i=0∑n−1​j=0∑n−1​d(i,j)

其中 d(i,j)d(i,j) 表示城市 ii 到城市 jj 之间灰尘度最小的路线对应的灰尘度的值。 为了改善出行环境, 每个城市都要有所作为, 当某个城市进行道路改善时, 会将与这个城市直接相连的所有道路的灰尘度都减少 1 , 但每条道路都有一个 灰尘度的下限值 LL, 当灰尘度达到道路的下限值时, 无论再怎么改善, 道路的 灰尘度也不会再减小了。

具体的计划是这样的:

第 1 天, 0 号城市对与其直接相连的道路环境进行改善;

第 2 天, 1 号城市对与其直接相连的道路环境进行改善;

⋯⋯

第 nn 天, n−1n−1 号城市对与其直接相连的道路环境进行改善;

第 n+1n+1 天, 0 号城市对与其直接相连的道路环境进行改善;

第 n+2n+2 天, 1 号城市对与其直接相连的道路环境进行改善;

LQ 国想要使得 PP 指标满足 P≤QP≤Q 。请问最少要经过多少天之后, PP 指标 可以满足 P≤QP≤Q 。如果在初始时就已经满足条件, 则输出 0 ; 如果永远不可能 满足, 则输出 −1−1 。

输入格式

输入的第一行包含两个整数 n,Qn,Q, 用一个空格分隔, 分别表示城市个数和 期望达到的 PP 指标。

接下来 nn 行, 每行包含 nn 个整数, 相邻两个整数之间用一个空格分隔, 其 中第 ii 行第 jj 列的值 Dij(Dij=Dji,Dii=0)Dij​(Dij​=Dji​,Dii​=0) 表示城市 ii 与城市 jj 之间直接相连 的那条道路的灰尘度。

接下来 nn 行, 每行包含 nn 个整数, 相邻两个整数之间用一个空格分隔, 其 中第 ii 行第 jj 列的值 Lij(Lij=Lji,Lii=0)Lij​(Lij​=Lji​,Lii​=0) 表示城市 ii 与城市 jj 之间直接相连的 那条道路的灰尘度的下限值。

输出格式

输出一行包含一个整数表示答条。

样例输入

复制代码
3 10
0 2 4
2 0 1
4 1 0
0 2 2
2 0 0
2 0 0

样例输出

复制代码
2

评测用例规模与约定

对于 30%30% 的评测用例, 1≤n≤10,0≤Lij≤Dij≤101≤n≤10,0≤Lij​≤Dij​≤10 ;

对于 60%60% 的评测用例, 1≤n≤50,0≤Lij≤Dij≤1000001≤n≤50,0≤Lij​≤Dij​≤100000;

对于所有评测用例, 1≤n≤100,0≤Lij≤Dij≤100000,0≤Q≤231−11≤n≤100,0≤Lij​≤Dij​≤100000,0≤Q≤231−1 。

复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=110,M=2*10010,MAX_CNT=2*10000010;     
       
    static int n,q;
    static int id=1;
    
    static int cnt=-1;
   
    static int dd[][]=new int[N][N];
    static int d[][]=new int[N][N];
    static int L[][]=new int[N][N];
    
    
    
    
//    static int h[]=new int[M];
//    static int e[]=new int[M];
//    static int ne[]=new int[M];
//    static int w[]=new int[M];
//    static boolean f[]=new boolean[10010];//是否确定了最短路径
    
    
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
    	
        StringTokenizer st=new StringTokenizer(br.readLine());
        n=Integer.parseInt(st.nextToken());  
        q=Integer.parseInt(st.nextToken());
    	
        for (int i = 1; i <= n; i++) {
        	st=new StringTokenizer(br.readLine());
        	for (int j = 1; j <= n; j++) {
				d[i][j]=Integer.parseInt(st.nextToken());
				d[j][i]=d[i][j];
			}
        }
        
        for (int i = 1; i <= n; i++) {
        	st=new StringTokenizer(br.readLine());
			for (int j = 1; j <= n; j++) {
				L[i][j]=Integer.parseInt(st.nextToken());
				L[j][i]=L[i][j];
			}
		}
        
       //对于每一个城市i (这里我们编号从一开始) 给定一个时刻t  我们需要知道他被改善的次数
       //次数等于t/n+(i<=t?1:0)也就是说先看看n个城市同时被改善的次数是多少
       //然后再加上剩下的次数 这个剩下的次数取决于i和t的大小
        
        
        //用二分枚举t
        int l=0,r=MAX_CNT;//保证都能取到下限值嗯
        while(l<r){
        	int mid=(l+r)>>1;
        	if(calc(mid)){
        		r=mid;
        	}else{
        		l=mid+1;
        	}
        }
        
        bw.write(cnt+"");
        
    	
        br.close();
        bw.flush();
        bw.close();
    }
    
    
    static boolean calc(int u){
    	int imporve[]=new int[n+1];//经过t天每个城市的改善次数
    	
    	for (int i = 1; i <= n; i++) {
			imporve[i]=u/n+(i-1<u%n?1:0);//注意没有等号
		}
    	for (int i = 0; i < N; i++) {
			System.arraycopy(d[i], 0, dd[i], 0, N);
		}
    	
    	for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				dd[i][j]=Math.max(L[i][j], dd[i][j]-imporve[i]-imporve[j]);
			}
		}
    	
    	//弗洛伊德算法
    	for (int k = 1; k <= n; k++) {
			for (int i = 1; i <= n; i++) {
				for (int j = 1; j <= n; j++) {
					dd[i][j]=Math.min(dd[i][j],dd[i][k]+dd[k][j]);
				}
			}
		}
    	
    	int res=0;
    	for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				res+=dd[i][j];
			}
		}
    	
    	if(res<=q){
    		cnt=u;
    		return true;
    	}
    	
    	return false;
    }
    
//    static void add(int a,int b,int c){
//    	e[id]=b;    	
//    	ne[id]=h[a];  
//    	w[id]=c;
//    	h[a]=id++;
//    }
       
}

染色时间

问题描述

小蓝有一个 nn 行 mm 列的白色棋盘, 棋盘的每一个方格都可以被染成彩色。

每个方格有一个染色时间 tijtij​, 不同方格的染色时间可能不同。如果一个方 格被触发了染色, 这个方格就会在 tijtij​ 秒之后变成彩色, 然后将自己上下左右四 个方向相邻的方格触发染色。每个方格只能被触发染色一次, 第一次触发之后 的触发为无效触发。

给定每个方格的染色时间, 在时刻 0 触发第一行第一列的方格染色, 请问 多长时间后整个棋盘完成染色。

输入格式

输入的第一行包含两个整数 n,mn,m, 分别表示棋盘的行数和列数。

接下来 nn 行, 每行 mm 个正整数, 相邻的整数之间用一个空格分隔, 表示每 个方格的染色时间。该部分的第 ii 行第 jj 个整数表示 tijtij​, 即第 ii 行第 jj 列的方 格的染色时间。

输出格式

输出一行包含一个整数, 表示整个棋盘完成染色的时间。

样例输入

复制代码
2 3

1 2 3

4 5 6

样例输出

复制代码
12

评测用例规模与约定

对于 3030 的评测用例, 1≤n,m≤101≤n,m≤10 。

对于 6060 的评测用例, 1≤n,m≤501≤n,m≤50 。

对于所有评测用例, 1≤n,m≤500,1≤tij≤10001≤n,m≤500,1≤tij​≤1000 。

复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=510;     
       
    static int n,m;
    static int id=1;
    
    static int cnt=-1;
   
    static boolean f[][]=new boolean[N][N];//当前点是否已经被染色
    static int a[][]=new int[N][N];
    static int dist[][]=new int[N][N];
    static int dx[]={0,-1,0,1};
    static int dy[]={1,0,-1,0};
    
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
    	
        StringTokenizer st=new StringTokenizer(br.readLine());
        n=Integer.parseInt(st.nextToken());  
        m=Integer.parseInt(st.nextToken());
    	
        for (int i = 1; i <= n; i++) {
        	st=new StringTokenizer(br.readLine());
			for (int j = 1; j <= m; j++) {
				a[i][j]=Integer.parseInt(st.nextToken());
			}
		}
        
        int res=0;
        //不可用BFS
        PriorityQueue<int[]> queue=new PriorityQueue<>((a,b)->a[2]-b[2]);
        queue.add(new int[]{1,1,a[1][1]});
        for (int i = 0; i < N; i++) {
			Arrays.fill(dist[i], Integer.MAX_VALUE);
		}
        dist[1][1]=a[1][1];
        while(!queue.isEmpty()){
        	int no[]=queue.poll();
        	int x=no[0],y=no[1],cur=no[2];
        	
        	if(!f[x][y]){
        		f[x][y]=true;
        		for (int i = 0; i < 4; i++) {
    				int nx=x+dx[i],ny=y+dy[i];
    				if(nx<1 || nx>n || ny<1 || ny>m)continue;
    				if(!f[nx][ny]){
    					if(cur+a[nx][ny]<dist[nx][ny]){
	    					dist[nx][ny]=cur+a[nx][ny];
	    					res=Math.max(res, dist[nx][ny]);
	    					queue.add(new int[]{nx,ny,dist[nx][ny]});
    					}
    					
    				}
    			}
        	}
        	
        }
        
        bw.write(res+"");
    	
        br.close();
        bw.flush();
        bw.close();
    }
    
    
       
}

小蓝组网

问题描述

给定一个含有 nn 个结点和 mm 条边的无向图,图中所有边的权值均为 11 ,且图中不包含重边。请判断该图中各点是否连通,并给出图中两个连通的点之间最短距离的最大值。

输入格式

输入第 11 行包括两个整数 n,mn,m ,分别表示图中结点的个数与边的个数。

第 2∼m+12∼m+1 行,每行包括两个整数 a,ba,b ,表示存在一条连接编号分别为 a,ba,b 的结点的无向边,结点编号范围从 11 到 nn 。

输出格式

输出两行,第 11 行判断图中各结点是否连通,若连通,则输出 YESYES ,否则输出 NONO 。 第 22 行输出两个连通的结点之间最短距离的最大值。

样例输入

复制代码
5 4
1 2
2 3
3 4
4 5

样例输出

复制代码
YES
4

说明

图中只有一个连通分量,必然是连通的,且两个连通的结点之间最短距离的最大值为 44 。

评测数据规模

对于 3030% 的评测数据,1≤n≤501≤n≤50, 1≤m≤1001≤m≤100 。

对于 5050% 的评测数据,1≤n≤2001≤n≤200, 1≤m≤100001≤m≤10000 。

对于 100100% 的评测数据,1≤n≤5001≤n≤500, 1≤m≤1051≤m≤105 。

复制代码
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.*;


public class Main {

    static int N=510;     
       
    static int n,m;
    static int id=1;
    
    static int cnt=-1;
   
   
    static int f[][]=new int[N][N];
   
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
    static BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(System.out));
    
    public static void main(String[] args) throws IOException { 
    	
        StringTokenizer st=new StringTokenizer(br.readLine());
        n=Integer.parseInt(st.nextToken());  
        m=Integer.parseInt(st.nextToken());
    	
        for (int i = 0; i < N; i++) {
			Arrays.fill(f[i], Integer.MAX_VALUE);
			f[i][i]=0;
		}
        
       for (int i = 0; i < m; i++) {
    	   st=new StringTokenizer(br.readLine());
    	   int a=Integer.parseInt(st.nextToken()),b=Integer.parseInt(st.nextToken());
    	   f[a][b]=1;
    	   f[b][a]=1;
       }
       
       for (int k = 1; k <= n; k++) {
		  for (int i = 1; i <= n; i++) {
			 for (int j = 1; j <= n; j++) {
				if(f[i][k]!=Integer.MAX_VALUE && f[k][j]!=Integer.MAX_VALUE){
					f[i][j]=Math.min(f[i][j], f[i][k]+f[k][j]);
				}
			}
		  }
       }
       
       boolean connect=true;
       int res=Integer.MIN_VALUE;
       for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= n; j++) {
				if(f[i][j]==Integer.MAX_VALUE)connect=false;
				else res=Math.max(res, f[i][j]);
			}
       }
       if(connect){
    	   bw.write("YES\n");
       }else{
    	   bw.write("NO\n");
       }
       
       bw.write(res+"");
       
    	
        br.close();
        bw.flush();
        bw.close();
    }
    
    

       
}
相关推荐
Ulyanov1 小时前
雷达导引头仿真中的坐标系——从惯性系到量测角
开发语言·python·算法·系统仿真·雷达信号处理·雷达导引头
玖玥拾1 小时前
LeetCode 13 罗马数字转整数
笔记·算法·leetcode
m沐沐2 小时前
【计算机视觉】OpenCV 物体跟踪——原理、算法与CSRT跟踪器实战
人工智能·python·深度学习·opencv·算法·计算机视觉·人脸识别
怪奇云呼军3 小时前
闪电智能 Voice Agent 怎样根据语速、停顿和追问方式切换话术?策略引擎拆解
开发语言·人工智能·网络协议·算法·语音识别·web app
稚南城才子,乌衣巷风流3 小时前
树链剖分(树剖)算法详解:从原理到实现
算法·深度优先
jz_ddk3 小时前
[信号处理] 数学与工程之美:相邻差分共轭乘积
数学·算法·信号处理·差分·共轭
m沐沐11 小时前
【深度学习】YOLOv2目标检测算法——改进点、网络结构与聚类先验框解析
人工智能·pytorch·深度学习·算法·yolo·目标检测·transformer
不会就选b11 小时前
算法日常・每日刷题--<链表>3
数据结构·算法·链表
geovindu12 小时前
go: Iterative Algorithms
开发语言·后端·算法·golang·迭代算法