SGU - 174 - Walls
上题目
Walls
ime Limit:1500MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
Description
People of country T-land lived on the big plain many years ago. It is happened so that they started to quarrel, so they began to build walls to separate from each other.
One day they realized that walls surround some part of the country. Your task is to determine which wall was build first to surround a part of the T-land.
One day they realized that walls surround some part of the country. Your task is to determine which wall was build first to surround a part of the T-land.
Input
The
first line of input contains one number M (1<=M<=200000) - number
of walls. Each of the following M lines contains four integer numbers:
Cartesian coordinates of two ends of each wall. Walls are rectilinear
segments with positive length, two walls can cross only by ends, and
walls can't coincide. All coordinates do not exceed 10^9 by its
absolute values.
Output
Write the answer in the single line of output. If all the walls leave the territory opened, write 0.
Sample Input
Input
4
0 0 1 0
0 1 0 0
1 0 0 1
2 2 5 7
0 0 1 0
0 1 0 0
1 0 0 1
2 2 5 7
Output
3
其实看懂了题目就是一道水的并查集。题意是给你最多200000条线段,不会重复,只会有可能端点相连或者没有任何接触。问你第几条线段出现的时候会出现封闭的图形,如果没有出现封闭的图形,输出0。
解法就是将线段上的点并入集合中,如果出现一条线段的两个端点在合并前就已经在同一个集合中的时候就说明已经围成封闭的图形了。
一开始没有看清题意,以为不可以出现同样的线段,但可以相交,于是就写了一段判断线段相交的代码,结果这段代码不可以判断负数,wa了好几次。后来又重写了2次,都是以线段为单位构成并查集,但是都wa了。其实一开始有想过以单个点为单位构成集合,可是当时没有想透彻,于是没有实现。同时这里我使用了map来处理,虽然速度上可能慢了一点,但是编程复杂度小了很多。
上代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <map> 4 #include <utility> 5 #define MAX 400000+10 6 using namespace std; 7 8 typedef pair<int,int> point; 9 int p[MAX],rank[MAX],tot; 10 map<point,int> r; 11 12 int findset(int x) 13 { 14 return x==p[x] ? x : findset(p[x]); 15 } 16 17 bool unionset(int x,int y) 18 { 19 x=findset(x); 20 y=findset(y); 21 if(x==y) return 1; 22 if(rank[x]>rank[y]) 23 { 24 p[y]=x; 25 } 26 else 27 { 28 p[x]=y; 29 if(rank[x]==rank[y]) rank[y]++; 30 } 31 return 0; 32 } 33 34 int main() 35 { 36 int i,j,m; 37 point a,b; 38 //freopen("data.txt","r",stdin); 39 memset(p,-1,sizeof(p)); 40 memset(rank,0,sizeof(rank)); 41 r.clear(); 42 tot=0; 43 scanf("%d",&m); 44 for(i=1;i<=m;i++) 45 { 46 scanf("%d %d",&a.first,&a.second); 47 scanf("%d %d",&b.first,&b.second); 48 if(r.count(a)<=0) {r[a]=tot; p[tot]=tot; tot++;} 49 if(r.count(b)<=0) {r[b]=tot; p[tot]=tot; tot++;} 50 if(unionset(r[a],r[b])) break; 51 } 52 for(j=i+1;j<=m;j++) 53 { 54 scanf("%d %d",&a.first,&a.second); 55 scanf("%d %d",&b.first,&b.second); 56 } 57 if(i<=m) printf("%d\n",i); 58 else printf("0\n"); 59 return 0; 60 }