Dijkstra算法解决URAL1072

Dijkstra算法的步骤:

1:集合初始化:集合Q置空,集合S中存所有节点

2:从集合S中取出最短路径点s(第一步时取起点),从S中移除,加入Q

3:松弛:s加入Q后,更新S集合中的距离

4:循环执行1,2,3直到S集合为空

 

关键点:

如果需要输出路径,应保存新加入节点的前置节点。对每个加入集合Q的节点,前置节点只有最多一个,后置节点有可能有多个。


import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;


public class URAL1072 {
	static {
        //System.setIn(URAL1072.class.getResourceAsStream("/URAL1072.txt"));
    }
    private static PrintWriter stdout = new PrintWriter(System.out);
    //private static StreamTokenizer stdin = new StreamTokenizer(new InputStreamReader(System.in));
    private static  Scanner stdin = new Scanner(System.in);
    
    private static int N;
    private static int START;
    private static int END;
    private static Computer[] allComputers = new Computer[90];
    private static Boolean[][] D = new Boolean[90][90];//two computer is connected or not

	/**
	 * @param args
	 */
	public static void main(String[] args) throws IOException {
		init();
		readData();
		//printMatrix();
		dijkstra();
		printResult();
	}
	
	private static void init()  {
		for (int i = 0; i < 90; i++) {
			allComputers[i] = null;
		}
		
		for (int i = 0; i < 90; i++) {
			for (int j = 0; j < 90; j++) {
				D[i][j] = Boolean.FALSE;
			}
		}
	}
	
	private static void readData() throws IOException {
		 N = stdin.nextInt();
		 for (int i = 0; i < N; i++) {
			 int K = stdin.nextInt();
			 IPAddress[] ips = new IPAddress[K];
			 for (int j = 0; j < K; j++) {
				 ips[j] = readIp();
			 }
			 Computer c = new Computer(i, ips);
			 allComputers[i] = c;
		 }
		 START = stdin.nextInt() - 1;
		 END = stdin.nextInt() - 1;
		 
		 
		 for (int i = 0; i < N; i++) {
			 for (int j = i + 1; j < N; j++) {
				 Computer computers1 = allComputers[i];
				 Computer computers2 = allComputers[j];
				 if (computers1.isTransmited(computers2)) {
					 D[i][j] = Boolean.TRUE;
					 D[j][i] = Boolean.TRUE;
				 } else {
					 D[i][j] = Boolean.FALSE;
					 D[j][i] = Boolean.FALSE;
				 }
			 }
		 }
	 }
	
	private static IPAddress readIp() throws IOException {
        String line = stdin.nextLine();
        while (line.trim().length() == 0) {
        	line = stdin.nextLine();
        }
        String[] ips = line.split(" ");
        int[] ip = parseIp(ips[0]);
        int[] mask = parseIp(ips[1]);
        
        IPAddress a = new IPAddress(ip, mask);
        return a;
    }
	
	private static int[] parseIp(String s) {
		String[] ips = s.split("\\.");
		int[] ip = new int[4];
		for (int i = 0; i < 4; i++) {
			ip[i]= Integer.parseInt(ips[i]);
		}
		return ip;
	}
	
	private static void dijkstra() {
		List<Computer> list1 = new ArrayList<Computer>(90);
		List<Computer> list2 = new ArrayList<Computer>(90);
		
		
		//init list2
		for (int i = 0; i < N; i++) {	
		   list2.add(allComputers[i]);	
		}
		
		while(!list2.isEmpty()) {
			int min = -1;
			Computer newComputer = null;
			if (!list1.isEmpty()) {
				for (Computer c : list2) {
					if (c.distance < min || min == -1) {
						newComputer = c;
						min = c.distance;
					}
				}
			} else {
				newComputer = allComputers[START];
				newComputer.distance = 0;
				newComputer.pre = null;
			}
			
			list2.remove(newComputer);
			list1.add(newComputer);
			
			if (newComputer.index == END) { //found,needn't to continue
				break;
			}
			
			if (newComputer.distance == Integer.MAX_VALUE) {
				break;
			}
			
			for (Computer c : list2) {
				if (D[newComputer.index][c.index]) {
					c.distance = newComputer.distance + 1;
					c.pre = newComputer;
				}
			}
		}
	}
	
	private static void printResult() {
		Computer end = allComputers[END];
		if (end != null && end.pre != null) {
			stdout.println("Yes");
			int[] result = new int[end.distance + 1];
			Computer c = end;
			int index = 0;
			while (c != null) {
				result[index++] = c.index;
				c = c.pre;
			}
			
			for (int i = result.length - 1; i >= 0; i --) {
				stdout.print(result[i] + 1);
				if (i != 0) {
					stdout.print(' ');
				}
			}
		} else {
			stdout.print("No");
		}
		stdout.println();
		stdout.flush();
	}
	
	static class IPAddress {
		public int[] ip;
		public int[] mask;
		public int[] subnet;
		
		public IPAddress(int[] ip, int[] mask) {
			this.ip = ip;
			this.mask = mask;
			this.subnet = IPAddress.getSubNet(ip, mask);
		}
		
		
		static int[] getSubNet(int[] ip, int[] mask) {
			int[] s = new int[4];
			for (int i = 0; i < 4; i++) {
				s[i] = ip[i] & mask[i];
			}
			return s;
		}
		
		public boolean isSubnetSame(IPAddress another) {
			for (int i = 0; i < 4; i++) {
				if (this.subnet[i] != another.subnet[i]) {
					return false;
				}
			}
			
			return true;
		}
	}
	
	static class Computer {
		public IPAddress[] ips;
		public int distance = 0;
		public int index;
		public Computer pre = null;//can't save next,cause there may be more than one 'next'
		
		public Computer(int index, IPAddress[] ips) {
			this.index = index;
			this.ips = ips;
			this.distance = Integer.MAX_VALUE;
		}
		
		//to determin whether this computer can transmit to the given one
		public boolean isTransmited(Computer another) {
			IPAddress[] ips1 = this.ips;
			IPAddress[] ips2 = another.ips;
			for (int x = 0; x < ips1.length; x++) {
				 IPAddress ip1 = ips1[x];
				 for (int y = 0; y < ips2.length; y++) {
					 IPAddress ip2 = ips2[y];
					 if (ip1 != null && ip2 != null && ip1.isSubnetSame(ip2)) {
						 return true;
					 }
				 }
			 }
			
			return false;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值