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 "); flag=1; break; } } if(flag==0) printf("YES "); } return 0; }