SGU 174 Walls

这题用并查集来做,判断什么时候形成了环即判断什么时候加入的线段两个端点原先是属于同一集合的。对于一个点,有两个坐标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;
}
View Code

记住这里要开两倍空间,因为每条线段有两个点。

原文地址:https://www.cnblogs.com/whatbeg/p/3505203.html