Codeforces 870E Points, Lines and Ready-made Titles:并查集【两个属性二选一】

题目链接:http://codeforces.com/problemset/problem/870/E

题意:

  给出平面坐标系上的n个点。

  对于每个点,你可以画一条经过这个点的横线或竖线或什么都不画。

  两条重合的直线算作一条直线。

  问你能画出多少种不同的图案。

题解:

  将所有横坐标或纵坐标相同的两点之间连边。

  对于一个连通块,设这个连通块中不同的横坐标个数为sx,不同的纵坐标个数为sy。

  有可能画出的线的个数即为sx + sy。

  可以发现,如果一个联通块中有环(即siz[fa] >= sx + sy)

  那么这sx + sy条边可以同时画出。

  否则必然有一条边不能画出。

  所以当前连通块的答案:有环为2^(sx+sy),无环为2^(sx+sy) - 1。

  将所有连通块的答案乘起来即为总答案。

AC Code:

  1 #include <iostream>
  2 #include <stdio.h>
  3 #include <string.h>
  4 #include <algorithm>
  5 #include <set>
  6 #define MAX_N 100005
  7 #define MAX_E 200005
  8 #define MOD 1000000007
  9
 10 using namespace std;
 11
 12 struct Coor
 13 {
 14     int x,y,id;
 15     Coor(int _x,int _y,int _id)
 16     {
 17         x=_x; y=_y; id=_id;
 18     }
 19     Coor(){}
 20 };
 21
 22 int n;
 23 int par[MAX_N];
 24 int siz[MAX_N];
 25 long long ans=1;
 26 long long pw[MAX_E];
 27 Coor c[MAX_N];
 28 set<int> sx[MAX_N];
 29 set<int> sy[MAX_N];
 30
 31 bool cmp1(const Coor &a,const Coor &b)
 32 {
 33     return a.y!=b.y ? a.y<b.y : a.x<b.x;
 34 }
 35
 36 bool cmp2(const Coor &a,const Coor &b)
 37 {
 38     return a.x!=b.x ? a.x<b.x : a.y<b.y;
 39 }
 40
 41 void read()
 42 {
 43     cin>>n;
 44     for(int i=1;i<=n;i++)
 45     {
 46         cin>>c[i].x>>c[i].y;
 47         c[i].id=i;
 48     }
 49 }
 50
 51 void init_union_find()
 52 {
 53     for(int i=1;i<=n;i++)
 54     {
 55         par[i]=i;
 56         siz[i]=1;
 57     }
 58 }
 59
 60 int find(int x)
 61 {
 62     return par[x]==x ? x : par[x]=find(par[x]);
 63 }
 64
 65 void unite(int x,int y)
 66 {
 67     int px=find(x);
 68     int py=find(y);
 69     if(px==py) return;
 70     siz[py]+=siz[px];
 71     par[px]=py;
 72 }
 73
 74 void build()
 75 {
 76     sort(c+1,c+1+n,cmp1);
 77     for(int i=1;i<n;i++)
 78     {
 79         if(c[i].y==c[i+1].y)
 80         {
 81             unite(c[i].id,c[i+1].id);
 82         }
 83     }
 84     sort(c+1,c+1+n,cmp2);
 85     for(int i=1;i<n;i++)
 86     {
 87         if(c[i].x==c[i+1].x)
 88         {
 89             unite(c[i].id,c[i+1].id);
 90         }
 91     }
 92 }
 93
 94 void cal_pow()
 95 {
 96     pw[0]=1;
 97     for(int i=1;i<MAX_E;i++) pw[i]=(pw[i-1]<<1ll)%MOD;
 98 }
 99
100 void cal_set()
101 {
102     for(int i=1;i<=n;i++)
103     {
104         sx[find(c[i].id)].insert(c[i].x);
105         sy[find(c[i].id)].insert(c[i].y);
106     }
107 }
108
109 inline long long mod(long long x)
110 {
111     return (x%MOD+MOD)%MOD;
112 }
113
114 void cal_ans()
115 {
116     for(int i=1;i<=n;i++)
117     {
118         int fa=find(i);
119         if(fa==i)
120         {
121             int edge=sx[fa].size()+sy[fa].size();
122             if(siz[fa]>=edge) ans=mod(ans*mod(pw[edge]));
123             else ans=mod(ans*mod(pw[edge]-1));
124         }
125     }
126 }
127
128 void work()
129 {
130     init_union_find();
131     build();
132     cal_pow();
133     cal_set();
134     cal_ans();
135     cout<<ans<<endl;
136 }
137
138 int main()
139 {
140     read();
141     work();
142 }

原文地址:https://www.cnblogs.com/Leohh/p/8468731.html

时间: 2024-08-30 11:57:56

Codeforces 870E Points, Lines and Ready-made Titles:并查集【两个属性二选一】的相关文章

Codeforces 870E Points, Lines and Ready-made Titles

题目传送门 传送门I 传送门II 传送门III 题目大意 平面上有$n$个点,第$i$个点可以画一条平行于$y$轴且经过这个点的直线或者平行于$x$轴且经过这个点的直线或者什么都不做,问能够产生多少种本质不同的图案. 考虑每个点与它$x$坐标相同且$y$坐标比它大的第一个点连一条无向边,以及与它$y$坐标相同且$x$坐标第一个比它大的点连一条无向边. 显然,每个连通块和连通块之间互不影响,所以分别考虑每个连通块. 设当前连通块所有点的横坐标构成的集合为$X$,纵坐标构成的集合为$Y$. 如果点数

Codeforces 1140F Extending Set of Points 线段树 + 按秩合并并查集 (看题解)

Extending Set of Points 我们能发现, 如果把x轴y轴看成点, 那么答案就是在各个连通块里面的x轴的个数乘以y轴的个数之和. 然后就变成了一个并查集的问题, 但是这个题目里面有撤销的操作, 所以我们要把加入和撤销操作变成 这个点影响(L , R)之间的询问, 然后把它丢到线段树里面分成log段, 然后我们dfs一遍线段树, 用按秩合并并查集取维护, 回溯的时候将并查集撤销. #include<bits/stdc++.h> #define LL long long #def

Codeforces Round #250 (Div. 1)B(排序+并查集)

B. The Child and Zoo time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output Of course our child likes walking in a zoo. The zoo has n areas, that are numbered from 1 to n. The i-th area contains 

Codeforces 745C:Hongcow Builds A Nation(并查集)

http://codeforces.com/problemset/problem/744/A 题意:在一个图里面有n个点m条边,还有k个点是受限制的,即不能从一个受限制的点走到另外一个受限制的点(有路径相连),问在这样的图里面遵守这样的规则可以最多添加几条边. 思路:这种题之前在做强连通的时候很常见,于是就写了tarjan..醒来后发现不用这么复杂,直接用并查集就可以做了. 1.对于每一个连通块,最多可以加上n*(n-1)/2条边. 2.对于受限制的连通块,取出一个点数最多的,和不受限制的块相连

Codeforces 776D.The Door Problem (dfs二分图判定 / 并查集)

题目链接: http://codeforces.com/problemset/problem/776/D 题意: n扇门,m个开关(n,m<=1e5),每个开关控制若干个门,反转开关门状态变化,每个门正好被两个开关控制,问是否有可能把所有门的状态置为1? 思路: from: http://blog.csdn.net/jeremy1149/article/details/56839453 方法一:二分图染色 注意到一个门只被两个开关控制 若门初始为0 则控制它的两个开关状态相反,门初始为1则 要求

Codeforces Round #170 (Div. 2)---C. Learning Languages(并查集)

The "BerCorp" company has got n employees. These employees can use m approved official languages for the formal correspondence. The languages are numbered with integers from 1 to m. For each employee we have the list of languages, which he knows

CodeForces - 891C: Envy(可撤销的并查集&amp;最小生成树)

For a connected undirected weighted graph G, MST (minimum spanning tree) is a subgraph of G that contains all of G's vertices, is a tree, and sum of its edges is minimum possible. You are given a graph G. If you run a MST algorithm on graph it would

CodeForces - 687D: Dividing Kingdom II (二分图&amp;带权并查集)

Long time ago, there was a great kingdom and it was being ruled by The Great Arya and Pari The Great. These two had some problems about the numbers they like, so they decided to divide the great kingdom between themselves. The great kingdom consisted

Codeforces 954I Yet Another String Matching Problem(并查集 + FFT)

题目链接  Educational Codeforces Round 40  Problem I 题意  定义两个长度相等的字符串之间的距离为:   把两个字符串中所有同一种字符变成另外一种,使得两个字符串相等所需要操作的次数的最小值.   求$s$中每一个长度为$t$的长度的连续子串与$t$的距离.字符集为小写字母$a$到$f$ 首先解决求两个长度相等的字符串之间的距离这个问题. $s$和$t$相同位上的字母连一条无向边,最后的答案是$s$和$t$中所有出现过的字符的个数减去这个无向图的连通块