题目大意就是给你N条线段,然后按照顺序添加线段,求出当添加入第几条线段时,已添加的某些线段组成了一个回路。 题意很好理解,算法也很容易出来,只要在添加某一条线段时,该线段的两个端点在之前就已经相连,那么加入这个线段后,就必然形成了一个回路。
判断这些点的联通性,一个算法呼之欲出,那就是并查集。可以给每个出现过的点一个编号,然后按照这个编号进行并查集即可。
比较恶心的地方就是给这个点添加编号,由于点是两维的,离散起来比较恶心,写平衡树也很恶心,那么我们就只能发挥C++的优势,使用字典的完美模型——map。不知道map的可以去翻翻c++ primer.里面写的很清楚。
只要设置一个pair代表点,在设置一个map代表点到编号的映射就可以了。
typedef pair<int,int> point;
map<point,int> point_map;
下面是我的代码。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = 4000010;
typedef pair<int,int> point;
typedef map<point,int>::value_type insert_val;
map<point,int> point_map;
int father[maxn];
int point_num,check_p1,check_p2;
int getfather(int p){
if (father[p] == p)
return p;
return (father[p]=getfather(father[p]));
}
int main(){
int i,j,k,n;
scanf("%d\n",&n);
for (i=1;i<=n;++i){
point p1,p2;
scanf("%d%d%d%d\n",&p1.first,&p1.second,&p2.first,&p2.second);
check_p1 = point_map.count(p1);
check_p2 = point_map.count(p2);
if (!check_p1){
point_map.insert(insert_val(p1,++point_num));
father[point_num] = point_num;
}
if (!check_p2){
point_map.insert(insert_val(p2,++point_num));
father[point_num] = point_num;
}
int p1_num = point_map[p1];
int p2_num = point_map[p2];
int p1_father = getfather(p1_num);
int p2_father = getfather(p2_num);
if (p1_father == p2_father){
printf("%d\n",i);
return 0;
}else
father[p1_father] = p2_father;
}
printf("0\n");
return 0;
}