FJUT ACM 2351 T^T的图论

T^T的图论

TimeLimit:3000MS  MemoryLimit:256MB
64-bit integer IO format:%lld
 
Problem Description

有一个坐标系,坐标系上有n个点,在同一行或同一列上的任意两点称为关联的,并且关联属性是可传递的,即A和B关联,B和C关联,则可认为A和C关联,现在问图中是否任意两点都是关联的。

Input

n>=2 && n<=50万

每个点的坐标x、y满足 1<=x、y<=50000

Output

如果是关联的,输出YES,否则,输出NO

SampleInput
2
1 1
3 3
3
1 1
1 3
3 3
SampleOutput
NO
YES

【思路】:感觉就是一题并查集的题,就是多了个排序操作而已,我先建了个结构体去储存
x和y,先对x进行排序,再对x相同的进行并查集的连接,接着再对y进行排序,再对y相同的
进行排序,然后再对y相同的进行并查集的连接,然后我wa了一发,为什么呢,因为我发现每次
排序后i的值发生变化,gg了,然后我就再加了个变量flag来标记,令flag=i;然后连接的时候
使用flag,就成功ac了一发。
附上代码:
#include<bits/stdc++.h>
#define MAXN 500005
using namespace std;
typedef struct MYINT
{
    int x;
    int y;
    int flag;
} myint;
myint math[MAXN];
int pre[MAXN];
void Init()
{
    for(int i=0; i<MAXN; i++)
    {
        pre[i]=i;
    }
}
int acfind(int x)
{
    return pre[x]==x?x:pre[x]=acfind(pre[x]);
}
int unionjoin(int x,int y)
{
    int a;
    int b;
    a=acfind(x);
    b=acfind(y);
    if(a!=b)
        pre[b]=a;
}
bool cmp1(myint a,myint b)
{
    return a.x>b.x;
}
bool cmp2(myint a,myint b)
{
    return a.y>b.y;
}
int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        Init();
        memset(math,0,sizeof(math));
        for(int i=0; i<n; i++)
            {scanf("%d %d",&math[i].x,&math[i].y);
            math[i].flag=i;
            }
        sort(math,math+n,cmp1);
        for(int i=1; i<n; i++)
        {
            if(math[i].x==math[i-1].x)
                unionjoin(math[i].flag,math[i-1].flag);
        }
        sort(math,math+n,cmp2);
        for(int i=1; i<n; i++)
        {
            if(math[i].y==math[i-1].y)
                unionjoin(math[i].flag,math[i-1].flag);
        }
        int ans=acfind(0);
        int flag=0;
        for(int i=1; i<n; i++)
        {
            if(ans!=acfind(i))
            {
                printf("NO\n");
                flag=1;
                break;
            }
        }
        if(flag==0)
            printf("YES\n");
    }
    return 0;
}

 

posted @ 2018-04-10 20:50  moxin0509  阅读(78)  评论(0编辑  收藏  举报