题目链接
C. Points, Lines and Ready-made Titles
分析
可以发现如果将相邻两个点(X,或者Y坐标相同)用一条边连起来,建一个无向图,那麽就可以单独考虑连通分量了,而一个连通分量中可以发现如果没有环,那麽答案是
2X+Y−1 X:=连通图里不同的X坐标 Y:=同上
如果有环
2X+Y
官方证明
其实只需要简单判定X+Y与连通分量点数的关系就可以知道是否有环
AC code
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define fi first
#define se second
#define mp make_pair
#define pb push_back
typedef long long LL;
const int maxn = 2e5+10;
const int MOD = 1e9+7;
LL num[maxn];
std::vector<int> G[maxn];
struct Point{
int val[2];
int id;
bool operator<(const Point &x)const{
return id < x.id;
}
};
Point a[maxn];
int CMP_IDX = 0;
bool cmp(const Point x,const Point y){
if(x.val[CMP_IDX] == y.val[CMP_IDX])return x.val[CMP_IDX^1]<y.val[CMP_IDX^1];
else return x.val[CMP_IDX]<y.val[CMP_IDX];
}
inline void add_edge(int x,int y){
G[x].pb(y);G[y].pb(x);
}
bool vis[maxn];
unordered_set<int> X,Y;
int cnt =0;
LL ans = 1;
void dfs(int u) {
vis[u] = 1;
X.insert(a[u].val[0]);
Y.insert(a[u].val[1]);
cnt++;
for(auto e : G[u]){
if(!vis[e]){
dfs(e);
}
}
}
int main()
{
num[0] =1;
for(int i=1 ; i<maxn ; ++i){
num[i] = 2*num[i-1] % MOD;
}
int n;
cin>>n;
for(int i=1 ; i<=n ; ++i){
scanf("%d%d",&a[i].val[0],&a[i].val[1] );
a[i].id = i;
}
for(CMP_IDX =0 ; CMP_IDX<=1 ; ++CMP_IDX){
sort(a+1,a+1+n,cmp);
for(int i=1 ; i<n ; ++i)
if(a[i].val[CMP_IDX] == a[i+1].val[CMP_IDX])
add_edge(a[i].id,a[i+1].id);
}
sort(a+1,a+n+1);
memset(vis,0,sizeof(vis));
for(int i=1 ; i<=n ; ++i){
if(!vis[i]){
X.clear();
Y.clear();
cnt=0;
dfs(i);
int sz= X.size()+Y.size();
if(cnt+1==sz){
ans = ans*(num[sz]-1+MOD)%MOD;//无环
}else ans = ans*num[sz]%MOD;
}
}
std::cout << ans << '\n';
}