这题用并查集来做,判断什么时候形成了环即判断什么时候加入的线段两个端点原先是属于同一集合的。对于一个点,有两个坐标x,y,不好做并查集操作,于是要用map来存储,即做成map<node,int>形式,每加入一条线段,如果没有出现过这一个/两个端点,则赋此条线段一个/两个端点一个类型,然后找他的两个端点是否原先在同一个集合即可。
代码:
#include <iostream> #include <cstdio> #include <map> using namespace std; #define N 400100 int fa[N]; struct node { int x,y; bool operator < (node a) const{ if (x==a.x) return y<a.y; else return x<a.x; } node (int _x,int _y):x(_x),y(_y){} }; map<node,int> mp; void makeset(int n) { for(int i=1;i<=2*n;i++) { fa[i] = i; } } int findset(int x) { if(x != fa[x]) { fa[x] = findset(fa[x]); } return fa[x]; } void unionset(int a,int b) { int x = findset(a); int y = findset(b); fa[x] = y; } int main() { int m,i,j; int a,b,c,d; while(scanf("%d",&m)!=EOF) { int type = 1; int flag = 0; makeset(m); for(i=1;i<=m;i++) { scanf("%d%d%d%d",&a,&b,&c,&d); if(flag == 0) { node ka = node(a,b); node kb = node(c,d); if(mp[ka]==0) mp[ka] = type++; if(mp[kb]==0) mp[kb] = type++; int x = mp[ka]; int y = mp[kb]; if(findset(x) == findset(y)) { flag = i; } else unionset(x,y); } } cout<<flag<<endl; } return 0; }
记住这里要开两倍空间,因为每条线段有两个点。