暂时只能想起这么几个题.......
A parity game
![](https://i-blog.csdnimg.cn/blog_migrate/6dc1e0740b1e80d6a081a8b9ee5462da.png)
![](https://i-blog.csdnimg.cn/blog_migrate/03bd5c86f2272b7b1d0a296be4ca4846.jpeg)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
const int N = 10010;
int n, m, cnt;
int p[N], d[N];
unordered_map<int, int> S;
// 离散化
int get(int x)
{
if (S.count(x) == 0) S[x] = ++ cnt;
return S[x];
}
int find(int x)
{
if (x != p[x])
{
int root = find(p[x]);//找到树根节点
d[x] ^= d[p[x]];// 节点x与到树根节点上的每个节点都相与。
p[x] = root;
}
return p[x];
}
int main()
{
S.clear();
scanf("%d%d", &n, &m);
for (int i = 0; i <= N; i ++) p[i] = i;
int res = m;
for (int i = 0; i < m; i ++)
{
int x, y, t;
char s[5];
scanf("%d%d%s", &x, &y, s);
// 注意是次数是x-1, 联想前缀和,(S[y] - S[x - 1])
x = get(x - 1), y = get(y);
t = s[0] == 'o';
int px = find(x), py = find(y);
// 如果属于同一个集合
if (px == py)
{
if ((d[x] ^ d[y]) != t) //奇偶性与答案不一致就break
{
res = i;
break;
}
} else {
p[px] = py;
d[px] = d[x] ^ d[y] ^ t; //此处是根据 t = d[x] ^ d[y] ^ d[px]推导而来
}
}
printf("%d\n", res);
return 0;
}
B 矩形
![](https://i-blog.csdnimg.cn/blog_migrate/1b176c8165e6a86acb9be7c06ff494e6.png)
![](https://i-blog.csdnimg.cn/blog_migrate/67332b5661be6c7573b07cdbd56cd819.png)
#include<bits/stdc++.h>
using namespace std ;
const int N = 1e6 + 10 , M = 1e5 ;
int n ;
int p[N] , cnt1[N] , cnt2[N] ;
int find(int x)
{
if(x != p[x]) p[x] = find(p[x]) ;
return p[x] ;
}
int main()
{
cin >> n ;
for(int i = 1 ; i <= N - 10 ; i ++) p[i] = i ;
for(int i = 1 ; i <= n ; i ++)
{
int x , y ;
scanf("%d %d",&x , &y) ;
p[find(x)] = find(y + M) ;
}
for(int i = 1 ; i <= M ; i ++) cnt1[find(i)] ++ ;
for(int i = M + 1 ; i <= 2 * M ; i ++) cnt2[find(i)] ++ ;
long long res = 0 ;
for(int i = 1 ; i <= 2 * M ; i ++) res += (long long)cnt1[i] * cnt2[i] ;
cout << res - n ;
return 0 ;
}
C Ladder Takahashi
https://atcoder.jp/contests/abc277/tasks/abc277_c
这个题多种写法,链式前向星或者并查集都可
![](https://i-blog.csdnimg.cn/blog_migrate/7e5423d9149e7f489012ff3e5176ea99.png)
C相比AB就没啥思维难度了
D Do use hexagon grid
https://atcoder.jp/contests/abc269/tasks/abc269_d
用并查集可以倒是可以但是好像....???是不是写的太麻烦了?
E 判环
const int N=1e6+10;
int p[N];
int find(int x){
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
signed main(){
int n,m;
while(cin>>n>>m){
if(!n && !m) break;
fer(i,1,n) p[i]=i;
bool fl=false;
fer(i,1,m){
int a,b;
cin>>a>>b;
if(find(a)!=find(b)){
p[find(a)]=find(b);
}
else{
fl=1;
break;
}
}
if(fl){
cout<<"YES\n";
}
else{
cout<<"NO\n";
}
}
}
abc的285的D - Change Usernames和这个就基本一模一样了(当然也有别的写法),纯板题
https://atcoder.jp/contests/abc285/tasks/abc285_d
#include <bits/stdc++.h>
using namespace std;
unordered_map<string, int>S;
int cnt;
const int N = 1e6;
int p[N];
int get(string x) {
if (S.count(x) == 0)
S[x] = ++cnt;
return S[x];
}
int find(int x) {
if (p[x] != x)
p[x] = find(p[x]);
return p[x];
}
int merge(int x, int y) {
int fx = find(x);
//cout << fx << " ";
int fy = find(y);
//cout << fy << endl;
if (fx == fy)
return 1;
p[fx] = fy;
return 0;
}
int main() {
int n;
cin >> n;
for (int i = 1; i < N; i++) {
p[i] = i;
}
while (n--) {
string s, t;
cin >> s >> t;
int u = get(s);
int o = get(t);
//cout << u << " " << o << endl;
if (merge(u, o)) {
cout << "No" << endl;
return 0;
}
}
cout << "Yes" << endl;
}