方法1:带权路径维护
本题核心:[a,b]之间有奇数个1转换为s[a-1]^s[b] = 1,从而转向并查集
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
const int N = 5010;
//d[i]表示i到根节点的异或值是1还是0
int f[N<<1],d[N<<1],sz[N<<1];
int find(int u)
{
if(f[u] == u) return u;
int t = find(f[u]);
d[u] ^= d[f[u]];
return f[u] = t;
}
void merge(int u,int v,int st)
{
int f1 = find(u), f2 = find(v);
//要求d[u]^d[f1]^d[v] = st,反推d[f1]
f[f1] = f2, d[f1]^=(d[u]^d[v]^st);
}
void solve()
{
int n;
cin>>n;
int m;
cin>>m;
for(int i=1;i<=m*2;++i) f[i] = i;
vector<array<int,3>> a(m);
for(int i=0;i<m;++i)
{
string op;
cin>>a[i][0]>>a[i][1]>>op;
//[a,b]中有奇数个1即s[a-1]和s[b]的奇偶性不同
vx.push_back(a[i][0]-1);
vx.push_back(a[i][1]);
if(op == "even") a[i][2] = 0;
else a[i][2] = 1;
}
//注意离散化需要erase掉重复的内容
divide();
for(int i=0;i<m;++i)
{
int u = mp(a[i][0]-1), v = mp(a[i][1]), st = a[i][2];
//cout<<u<<' '<<v<<' '<<st<<'\n';
if(find(u) == find(v))
{
if(d[u]^d[v] != st)
{
cout<<i<<'\n';return ;
}
}
else
{
merge(u,v,st);
}
}
cout<<m<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T = 1;
//cin>>T;
while(T--)
{
solve();
}
}
方法2扩展域
#include<bits/stdc++.h>
using namespace std;
#define x first
#define y second
typedef pair<int,int> PII;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef vector<string> VS;
typedef vector<int> VI;
typedef vector<vector<int>> VVI;
vector<int> vx;
inline void divide() {sort(vx.begin(),vx.end());vx.erase(unique(vx.begin(),vx.end()),vx.end());}
inline int mp(int x) {return upper_bound(vx.begin(),vx.end(),x)-vx.begin();}
inline int log_2(int x) {return 31-__builtin_clz(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int lowbit(int x) {return x&-x;}
const int N = 5010;
//d[i]表示i到根节点的异或值是1还是0
int f[N<<2];
int find(int u)
{
if(f[u] == u) return u;
return f[u] = find(f[u]);
}
void merge(int u,int v)
{
int f1 = find(u), f2 = find(v);
f[f1] = f2;
}
void solve()
{
int n;
cin>>n;
int m;
cin>>m;
//拆点
for(int i=1;i<=m*4;++i) f[i] = i;
vector<array<int,3>> a(m);
for(int i=0;i<m;++i)
{
string op;
cin>>a[i][0]>>a[i][1]>>op;
//[a,b]中有奇数个1即s[a-1]和s[b]的奇偶性不同
vx.push_back(a[i][0]-1);
vx.push_back(a[i][1]);
if(op == "even") a[i][2] = 0;
else a[i][2] = 1;
}
//注意离散化需要erase掉重复的内容
divide();
//用i*2表示i的偶数点,用i*2-1表示i的奇数点,表示sum[i]是奇数或者偶数
for(int i=0;i<m;++i)
{
int u = mp(a[i][0]-1), v = mp(a[i][1]), st = a[i][2];
int ue = u*2, uo = u*2-1, ve = v*2, vo = v*2-1;
//若st == 1则uo应该和ve合并,ue和vo合并
if(st)
{
if(find(uo) == find(vo)||find(ue) == find(ve))
{
cout<<i<<'\n';return ;
}
merge(uo,ve);merge(ue,vo);
}
else
{
if(find(ue) == find(vo)||find(uo) == find(ve))
{
cout<<i<<'\n';return ;
}
merge(uo,vo);merge(ue,ve);
}
}
cout<<m<<'\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T = 1;
//cin>>T;
while(T--)
{
solve();
}
}
标签:Parity,typedef,int,查集,begin,long,Game,vx,inline
From: https://www.cnblogs.com/ruoye123456/p/18439505