连接重新挂载的部分可以优化
package com.company.real;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.*;
//栅栏2 20190731真题
public class Zhalan_20190731 {
static int[] set;//保存点的父id
static Map<String,Integer> map;// 1_1,1
static Node0731[] nodes;//保存nodes节点,100000个铁丝网,最多可以连接100001个点
static List<Edge0731>[] list;//存放每一个点(使用find后的数据) 相连的边
static int N;
static int Max_x=1087654321;
//static int Max_y=2137654321;
public static void main(String[] args) throws Exception{
//System.setIn(new FileInputStream("C:\\Users\\XAGDC\\Desktop\\32Pro\\sample_input.txt"));
System.setIn(new FileInputStream("C:\\Users\\XAGDC\\Desktop\\32Pro\\eval_input.txt"));
BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st=new StringTokenizer(reader.readLine());
int T=Integer.parseInt(st.nextToken());//测试用例的个数
for (int zz = 0; zz < T; zz++) {
map=new HashMap<String,Integer>();
nodes=new Node0731[100001];
st=new StringTokenizer(reader.readLine());
N=Integer.parseInt(st.nextToken());//铁丝网的个数
set=new int[N+1];
list=new ArrayList[N+1];
for (int i = 0; i <set.length ; i++) {
set[i]=i;
list[i]=new ArrayList<Edge0731>();
}
int index=-1;
for (int i = 0; i <N ; i++) {//接收N个铁丝网
st=new StringTokenizer(reader.readLine());
int sx=Integer.parseInt(st.nextToken());
int sy=Integer.parseInt(st.nextToken());
int ex=Integer.parseInt(st.nextToken());
int ey=Integer.parseInt(st.nextToken());
String ss=sx+"_"+sy;
String es=ex+"_"+ey;
if(map.get(ss)==null){
index++;
map.put(ss,index);
nodes[index]=new Node0731(sx,sy);
}
if(map.get(es)==null){
index++;
map.put(es,index);
nodes[index]=new Node0731(ex,ey);
}
int a=map.get(ss);
int b=map.get(es);
if(!connected(a,b)){//如果没有相连,把这两个点连接起来
union(a,b);
}
int m=a<b?a:b;
list[find(m)].add(new Edge0731(sx,sy,ex,ey));
}
topUnion();//把所有的节点,都压缩到顶级节点,防止路径压缩不彻底的情况
for (int i = 0; i <list.length ; i++) {
List<Edge0731> li=list[i];
if(li!=null && li.size()>0){
if(set[i]!=i){
int PI=set[i];
list[PI].addAll(li);
list[i]=null;
}
}
}
//System.out.println(Arrays.toString(set));
//if(zz==2)System.out.println(Arrays.toString(nodes));
//接收两个测试的点N1 N2
String [] str=reader.readLine().split(" ");
Node0731 N1=new Node0731(Integer.parseInt(str[0]) ,Integer.parseInt(str[1]));
str=reader.readLine().split(" ");
Node0731 N2=new Node0731(Integer.parseInt(str[0]) ,Integer.parseInt(str[1]));
int count=0;
//System.out.printf("第 %d 个用例 \n",(zz+1));
for (int i=0;i<list.length;i++) {
List<Edge0731> l=list[i];
if(l!=null && l.size()>0){
//if(zz==2)System.out.println(i+" pid: "+set[i]+" "+l);
boolean r1=checkINOUT(l,N1);
boolean r2=checkINOUT(l,N2);
if((r1 && !r2) || (!r1 && r2)){// 两个结果不一样才需要穿越 两个都在里面,或者都在外面,不需要穿越
count++;
}
}
}
System.out.printf("#%d %d \n",(zz+1),count);
}
reader.close();
}
/**
*
* @param li
* @param C
* @return 在里面返回true,在外面返回false
*/
static boolean checkINOUT(List<Edge0731> li,Node0731 C){
boolean result=false;
int m=0;
//Node0731 D=new Node0731(C.x+1,Max_y+101);
Node0731 D=new Node0731(Max_x,C.y+1);
for (int i = 0; i < li.size(); i++) {
Edge0731 e=li.get(i);
Node0731 A=new Node0731(e.sx,e.sy);
Node0731 B=new Node0731(e.ex,e.ey);
if(cross_check(A,B,C,D)){
m++;
}
}
//System.out.printf("点(%d,%d) 的相交个数 %d \n",C.x,C.y,m);
if(m%2==1){//奇数,点在里面
result=true;
}
return result;
}
public static void topUnion(){
for (int i = 0; i <set.length ; i++) {
set[i]=find(i);
}
}
public static int find(int a){
if(set[a]==a){
return set[a];
}else{
return set[a]=find(set[a]);
}
}
public static void union(int a,int b){
int A=find(a);
int B=find(b);
if(A!=B){
if(A<B){//把B挂到A上面
set[B]=A;
}else{
set[A]=B;
}
}
}
public static boolean connected(int a,int b){
int A=find(a);
int B=find(b);
return A==B;
}
static boolean cross_check(Node0731 A,Node0731 B,Node0731 C,Node0731 D){
int abc=direction(A,B,C);
int abd=direction(A,B,D);
int cda=direction(C,D,A);
int cdb=direction(C,D,B);
if(abc*abd <=0 && cda*cdb<=0){
//if(abc*abd <0 && cda*cdb<0){
//System.out.printf("ABCD相交 A(%d,%d)->B(%d,%d) C(%d,%d)->D(%d,%d) \n",A.x,A.y,B.x,B.y,C.x,C.y,D.x,D.y);
return true;
}else{
//System.out.printf("ABCD不相交 A(%d,%d)->B(%d,%d) C(%d,%d)->D(%d,%d) \n",A.x,A.y,B.x,B.y,C.x,C.y,D.x,D.y);
return false;
}
}
public static int direction(Node0731 A,Node0731 B,Node0731 C){
int dxAB=B.x-A.x;
int dyAB=B.y-A.y;
int dxAC=C.x-A.x;
int dyAC=C.y-A.y;
int abc=BigInteger.valueOf(dxAB).multiply(BigInteger.valueOf(dyAC)).compareTo(BigInteger.valueOf(dyAB).multiply(BigInteger.valueOf(dxAC)));
//int abc=dxAB*dyAC
//int abc=dxAB*dyAC-dyAB*dxAC;
if(abc>0){
return -1;//顺时针
}else if(abc<0){
return 1;//逆时针
}else{
return 0;//A和B在一个点上
}
}
}
class Node0731{
int x;
int y;
public Node0731(int x, int y) {
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "Node0731{" +
"x=" + x +
", y=" + y +
'}';
}
}
class Edge0731{
int sx;
int sy;
int ex;
int ey;
public Edge0731(int sx, int sy, int ex, int ey) {
this.sx = sx;
this.sy = sy;
this.ex = ex;
this.ey = ey;
}
@Override
public String toString() {
return "Edge0731{" +
"sx=" + sx +
", sy=" + sy +
", ex=" + ex +
", ey=" + ey +
'}';
}
}
这篇博客探讨了在SW练习中遇到的栅栏问题,结合UnionFind数据结构进行了解决,并提及了如何优化连接重新挂载的部分,同时涉及到凸包算法的应用。
942

被折叠的 条评论
为什么被折叠?



