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;
}
}
}
}