并查集Poj

POJ_2492 A Bug’s Life

用两倍的数组表示,当输入x, y时,(两者为异性),那么x + n, y 和 x, y + n 则为同性(合并即可),(食物链的化简版)

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Poj_2492 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static final int MAXN = 5000;
	static int par[] = new int[MAXN];

	public static void main(String[] args) throws IOException {
		int t, n, m;
		t = nextInt();
		for(int i = 1; i <= t; i++) {
			n = nextInt();
			m = nextInt();
			Init(n * 2);
			boolean flag = true;
			int x, y;
			while(m-- >0) {
				x = nextInt();
				y = nextInt();
				if(judge(x, y) || judge(x + n, y + n)) {
					Union(x, y + n);
					Union(x + n, y);
				}else {
					flag = false;
				}
				
			}
			
			if(i != 1) {
				out.println();
			}
			out.println("Scenario #" + i + ":");
			if(flag) {
				out.println("No suspicious bugs found!");
			}else {
				out.println("Suspicious bugs found!");
			}
			out.flush();
		}
		
	}

	public static void Init(int n) {
		for (int i = 0; i <= n; i++) {
			par[i] = i;
		}
	}

	public static int find(int x) {
		if (x != par[x]) {
			par[x] = find(par[x]);
		}
		return par[x];
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

	public static boolean judge(int x, int y) {
		x = find(x);
		y = find(y);
		if (x != y) {
			return true;
		}
		return false;
	}

}

POJ_2524 Ubiquitous Religions

每次合并输入的两个数,最后找一个有几个父亲结点即可,(这里我用的是set集合处理的)

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.HashSet;

public class Poj_2524 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}
	static int par[] = new int[50005];
	
	public static void main(String[] args) throws IOException {
		int n, m, cas = 1;
		while(true) {
			n = nextInt();
			m = nextInt();
			if(n == 0 && m == 0) {
				break;
			}
			Init(n);
			int x, y;
			for(int i = 0; i < m; i++) { // m次询问、
				x = nextInt();
				y = nextInt();
				Union(x, y);
			}
			
			HashSet set = new HashSet();
			for(int i = 1; i <= n; i++) {
				set.add(find(i));
			}
			out.println("Case " + (cas++) + ": " + set.size());
			out.flush();
		}
		
	}
	
	public static void Init(int n) {
		for(int i = 0; i <= n; i++) {
			par[i] = i;
		}
	}
	
	public static int find(int x) {
		if(x != par[x]) {
			par[x] = find(par[x]);
		}
		return par[x];
	}
	
	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if(x != y) {
			par[x] = y;
		}
	}
	
	

}

POJ_1182 食物链

开三倍的数组,x , x + n, x + 2n,分别表示,同类,被捕食,捕食者,如果输入得是捕食关系的话那就合并,x , y + n和 

x + n, y + 2n和  x + 2n , y 、  同类的话, 合并 x, y 和 x + n , y + n, 和 x + 2n, y + 2n,如果同之前的记录有冲突,那么假话++,

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Poj_1182 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static int par[] = new int[150005];

	public static void main(String[] args) throws IOException {
		int n, k, ans = 0;
		int d, x, y;
		n = nextInt();
		k = nextInt();
		Init(n * 3);
		while (k-- > 0) {
			d = nextInt();
			x = nextInt();
			y = nextInt();
			if (x > n || y > n) {
				ans++;
				continue;
			}
			if (d == 1) { // 第一种关系、同类 (不能出现捕食关系、与被捕食关系)
				if (same(x, y + n) || same(x, y + 2 * n)) {
					ans++;
				} else {
					Union(x, y);
					Union(x + n, y + n);
					Union(x + 2 * n, y + 2 * n);
				}
			} else { // 捕食关系 (不能出现同类,和反捕食的关系)
				if (same(x, y) || same(x, y + 2 * n)) {
					ans++;
				} else {
					Union(x, y + n);
					Union(x + n, y + 2 * n);
					Union(x + 2 * n, y);
				}
			}
		}
		out.println(ans);
		out.flush();
	}

	public static void Init(int n) {
		for (int i = 0; i <= n; i++) {
			par[i] = i;
		}
	}

	public static int find(int x) {
		if (x != par[x]) {
			par[x] = find(par[x]);
		}
		return par[x];
	}

	public static boolean same(int x, int y) {
		return find(x) == find(y);
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

}

POJ_1861 Network

这里用到了并查集,自定义排序,和求最小生成树,

定义一个电缆类,存储可连通的集线器的种类,以及该电缆的长度,然后定义一个比较器,对电缆的长度进行排序,

再利用kruskal算法求最小生成树,以及合并每次连通的两个集线器,(遍历所有的电缆不是连通的就合并,最后生成的就是最小生成树)

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;

public class Poj_1861 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static Node node[] = new Node[15005];
	static int par[] = new int[15005];
	static boolean vis[] = new boolean[15005];
	static int n, m, ans; // 记录使用的最长的电缆的长度、
	public static void main(String[] args) throws IOException {
		n = nextInt();
		m = nextInt();
		Init(n);
		int a, b, zz;
		for (int i = 0; i < m; i++) {
			a = nextInt();
			b = nextInt();
			zz = nextInt();
			node[i] = new Node(a, b, zz);
		}
/*		out.println("看看输入是否正确:");
		for(int i = 0; i < m; i++) {
			out.println(node[i].x + " " + node[i].y + " " + node[i].cost);
		}
		out.println("-----我是和谐的分界线-----");
		
		
		
		out.println("看看输入是否正确:");
		for(int i = 0; i < m; i++) {
			out.println(node[i].x + " " + node[i].y + " " + node[i].cost);
		}
		out.println("-----我是和谐的分界线-----"); */
		Arrays.sort(node, 0, m);
		ans = 0;
		// 形成最小生成树、
		int num = kruskal();
		out.println(ans);
		out.println(num);
		for(int i = 0; i < m; i++) {
			if(vis[i]) {
				out.println(node[i].x + " " + node[i].y);
			}
		}
		out.flush();
	}
	
	public static int kruskal() {
		int num = 0;
		for(int i = 0; i < m; i++) {
			Node tmp = node[i]; // 取出当前最小的电缆、
			if(!same(tmp.x, tmp.y)) {
				Union(tmp.x, tmp.y);
				ans = Math.max(ans, tmp.cost);  // 电缆的长度更新、
				vis[i] = true; // 标记使用了、
				num++;  // 使用的电缆数 ++
			}
		}
		return num;
	}

	public static void Init(int n) {
		for (int i = 0; i <= n; i++) {
			par[i] = i;
			vis[i] = false;
		}
	}

	public static int find(int a) {
		if(par[a] != a) {
			par[a] = find(par[a]);
		}
		return par[a];
	}

	public static boolean same(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x == y) {
			return true;
		}
		return false;
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

	static class Node implements Comparable<Node> {
		int x, y, cost;

		Node(int x, int y, int dis) {
			this.x = x;
			this.y = y;
			this.cost = dis;
		}

		Node() {
		}

		@Override
		public int compareTo(Node o) {
			return this.cost - o.cost;
		}
	}

}

POJ_1703 Find them,Catch them

这个可以用食物链的简化版,同样的是开两倍的数组,输入D :x,y 不同帮派,那我们就合并 x , y + n 和 x + n, y 为同一帮派,当输入A检查时,判断是否是同伙,不同伙,以及无法判断,

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Poj_1703 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static int par[] = new int[100005 * 2];

	public static void main(String[] args) throws IOException {
		int t = nextInt();
		while(t-->0) {
			int n , m;
			n = nextInt();
			m = nextInt();
			Init(n * 2);
			String s = "";
			int a, b;
			for(int i = 0; i < m; i++) {
				s = next();
				a = nextInt();
				b = nextInt();
				if(s.charAt(0) == 'A') { // 判断是否同伙、、
					if(same(a, b) || same(a + n, b + n)) { // 同伙
						out.println("In the same gang.");
					}else if(same(a, b + n) && same(a + n, b)) {
						out.println("In different gangs.");
					}else {
						out.println("Not sure yet.");
					}
					out.flush();
				}else { // 不同伙、、
					Union(a, b + n);
					Union(a + n, b);
				}
			}
		}
	}

	public static void Init(int n) {
		for (int i = 0; i <= n; i++) {
			par[i] = i;
		}
	}

	public static int find(int a) {
		if (par[a] != a) {
			par[a] = find(par[a]);
		}
		return par[a];
	}

	public static boolean same(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x == y) {
			return true;
		}
		return false;
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

}

POJ_2236 Wireless Network

当修复结点的时候,遍历所有的情况、看看修复的电脑中,是否和该修复的电脑,在最大通信范围之内,如果是的话,就合并,但要注意的是,如果刚好在最大范围上呢,这个double类型相等的情况杂比较,(*^__^*)  (注意下标从1开始,好几次空指针异常)

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;

public class Poj_2236 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static int par[] = new int[1005];
	static boolean repair[] = new boolean[1005];
	static Node node[] = new Node[1005];
	public static void main(String[] args) throws IOException {
		int n, d;
		n = nextInt(); // 计算机数量 、
		d = nextInt(); // 最大的距离、、
		int x, y;
		Init(n);
		for(int i = 1; i <= n; i++) { //输入结点的坐标、、
			x = nextInt();
			y = nextInt();
			node[i] = new Node(x, y);
		}
		
		String s;
		int q, p;
		while(in.nextToken() != StreamTokenizer.TT_EOF) {
			s = in.sval; 
			if(s.charAt(0) == 'O') { // 修复计算机、、
				q = nextInt();
				repair[q] = true;
				for(int i = 1; i <= n; i++) { // 遍历一遍、 周围可以通讯的都合并起来、
					if(i != q && repair[i] && distance(node[i], node[q]) <= (double)(d)) {  // 不是自己, 修复好了, 而且距离小于最大的连通距离、
						Union(i, q);
					}
				}
			}else if(s.charAt(0) == 'S') {
				q = nextInt();
				p = nextInt();
				if(same(q, p)) {
					out.println("SUCCESS");
				}else {
					out.println("FAIL");
				}
				out.flush();
			}
		}
	}

	static class Node {
		int x, y;

		Node(int x, int y) {
			this.x = x;
			this.y = y;
		}

		Node() {
		}
	}

	public static double distance(Node a, Node b) { // 计算出两台计算机 ,相距的距离、、
		return Math.sqrt((double)((a.x - b.x) * (a.x - b.x)) + (double)((a.y - b.y) * (a.y - b.y)));
	}

	public static void Init(int n) {
		for (int i = 0; i <= n; i++) {
			par[i] = i;
			repair[i] = false;
		}
	}

	public static int find(int a) {
		if (par[a] != a) {
			par[a] = find(par[a]);
		}
		return par[a];
	}

	public static boolean same(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x == y) {
			return true;
		}
		return false;
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

}

Poj_2506:Freckles

这个题目输入的是点的坐标,然后让我们连线(输出最小的连接长度)、

这个有两种方法、

1、Prim算法:随便以一个点为起点、计算出其他的点到该点的直线距离,选取最小的添加带集合中,然后用这个点更新其他的距离,(选取最小的)

2:计算所有点距离其他点的坐标,添加进入优先队列中,(距离近的在前面),每次取出最小的,父节点相同?pass ,不同合并,灯集合的元素全部空了,或者合并的点到了n都可以结束,最后输出。

思路一代码:

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.math.BigDecimal;

public class Poj_2560_ {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static double mincost[] = new double[105];
	static double dist[] = new double[105];
	static boolean vis[] = new boolean[105];
	static Node node[] = new Node[105];

	public static void main(String[] args) throws IOException {
		int n = nextInt();
		double x , y;
		for(int i = 0; i < n; i++) {
			in.nextToken(); x = in.nval;
			in.nextToken(); y = in.nval;
			node[i] = new Node(x, y);
		}
		prim(n);
		double ans = 0.0;
		for(int i = 0; i < n - 1; i++) {
			ans += mincost[i];
		}
		BigDecimal bd = new BigDecimal(ans).setScale(2, BigDecimal.ROUND_HALF_DOWN);
		out.println(bd);
		out.flush();
		
	}

	public static void prim(int n) {
		for(int i = 0; i < n; i++) {
			vis[i] = false;
			if(i != 0) {
				dist[i] = caldist(0, i);
			}
		}
		dist[0] = 0;
		vis[0] = true;
		for(int i = 0; i < n; i++) {
			double minD = Double.MAX_VALUE;
			int id = 0;
			for(int j = 1; j < n; j++) {
				if(!vis[j] && dist[j] < minD) {
					minD = dist[j];
					id = j;
				}
			}
			
			vis[id] = true;
			mincost[i] = minD;
			for(int j = 1; j < n; j++) {
				if(!vis[j]) {
					double zz = caldist(id, j);
					dist[j] = Math.min(zz, dist[j]);
				}
			}
		}
	}

	public static double caldist(int a, int b) {
		double x = node[a].x - node[b].x;
		double y = node[a].y - node[b].y;
		return Math.sqrt(x * x + y * y);
	}

	public static void Init(int n) {
		for (int i = 0; i < n; i++) {
			node[i] = new Node();
		}
	}

	static class Node {
		double x, y;

		Node(double x, double y) {
			this.x = x;
			this.y = y;
		}

		Node() {
		}

	}

}

思路二代码:

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.math.BigDecimal;
import java.util.PriorityQueue;

public class Poj_2560 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static Node node[] = new Node[105];
	static int par[] = new int[105];
	static PriorityQueue<Node> q = new PriorityQueue<Node>();
	static int n;
	static double sum;

	public static void main(String[] args) throws IOException {
		q.clear();
		n = nextInt();

		int x, y;
		for (int i = 0; i < n; i++) {
			x = nextInt();
			y = nextInt();
			node[i] = new Node(x, y); // 输入的位置的坐标,,
		}
		sum = 0;
		Init(n);
		while (!q.isEmpty()) {
			Node tmp = q.poll();
			if (!same(tmp.x, tmp.y)) {
				sum += tmp.len;
				Union(tmp.x, tmp.y);
			}
		}
		BigDecimal bd = new BigDecimal(sum).setScale(2, BigDecimal.ROUND_HALF_DOWN);
		out.println(bd);
		out.flush();

	}

	public static boolean same(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x == y) {
			return true;
		}
		return false;
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

	public static int find(int a) {
		if (par[a] != a) {
			par[a] = find(par[a]);
		}
		return par[a];
	}

	public static void Init(int n) {
		for (int i = 0; i <= n; i++) {
			par[i] = i;
		}

		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				if (i == j) {
					continue;
				}
				double dis = Math.sqrt((node[i].x - node[j].x) * (node[i].x - node[j].x)
						+ (node[i].y - node[j].y) * (node[i].y - node[j].y));
				q.add(new Node(i, j, dis));
			}
		}
	}

	public static class Node implements Comparable<Node> {
		int x, y;
		double len;

		Node(int x, int y) {
			this.x = x;
			this.y = y;
		}

		Node(int x, int y, double len) {
			this.x = x;
			this.y = y;
			this.len = len;
		}

		Node() {
		}

		@Override
		public int compareTo(Node o) {
			if (this.len < o.len) {
				return -1;
			} else if (this.len > o.len) {
				return 1;
			} else {
				return 0;
			}
		}

	}

}

Poj_1456 Supermarket

贪心求解,(贪心策略为,优先销售利润最大的、销售时间,放在截止日期之前最近的未被占用的一天)然后并查集合并

package POJ;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.PriorityQueue;

public class Poj_1456 {
	static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));

	public static int nextInt() throws IOException {
		in.nextToken();
		return (int) in.nval;
	}

	public static String next() throws IOException {
		in.nextToken();
		return (String) in.sval;
	}

	static int par[] = new int[10005];

	public static void main(String[] args) throws IOException {
		while (in.nextToken() != StreamTokenizer.TT_EOF) {
			int n = (int) in.nval;
			PriorityQueue<Node> q = new PriorityQueue<Node>();
			Init();
			int x, y;
			for (int i = 0; i < n; i++) {
				x = nextInt();
				y = nextInt();
				q.add(new Node(x, y));
			}

			long sum = 0;
			int z;
			while (!q.isEmpty()) { // 优先队列不为空, 弹出来、
				Node zz = q.poll();
				z = find(zz.d);
				if(z > 0) {
					sum += zz.p;
					par[z] = z - 1;
				}
			}
			out.println(sum);
			out.flush();
		}

	}

	public static void Init() {
		for (int i = 0; i < 10005; i++) {
			par[i] = i;
		}
	}

	public static boolean same(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x == y) {
			return true;
		}
		return false;
	}

	public static void Union(int a, int b) {
		int x = find(a);
		int y = find(b);
		if (x != y) {
			par[x] = y;
		}
	}

	public static int find(int a) {
		if (par[a] != a) {
			par[a] = find(par[a]);
		}
		return par[a];
	}

	static class Node implements Comparable<Node> {
		int p, d;

		public Node(int p, int d) {
			this.p = p;
			this.d = d;
		}

		public Node() {
		}

		@Override
		public int compareTo(Node o) {
			if (this.p == o.p) {
				return this.d - o.d;
			} else {
				return o.p - this.p;
			}

		}

	}

}


猜你喜欢

转载自blog.csdn.net/qq_36706625/article/details/79936217