CF553C Love Triangles(带权并查集)
Posted 吃花椒的妙酱
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF553C Love Triangles(带权并查集)相关的知识,希望对你有一定的参考价值。
维护集合关系,可以用拓展域并查集,2sat,带权并查集
其中带权并查集难理解(不过代码短,个人认为
2sat和并查集的主要区别在于,并查集可以维护两者是否属于一类的问题,而2sat相比于其维护的范围更广一点,可以带逻辑的推理p->q,非p->q之类的...
以下用带权并查集..
CF553C Love Triangles
给出n个点,要求构造合法的完全图,已经给出了一些边。
边有爱边和恨边,其中任意三个点,连成的边合法的组合有爱爱爱,爱恨恨。
问符合要求的完全图的数量,对1e9+7取模.n<=1e5
思路:
显然对于三个点,若已知两边则第三边也确定了。如果已知一边,则其他两边有两种选择
不妨设爱的边权为0,恨为1,那么符合的三个点之间三条边的异或值为0。
我们把点连好后,输入完,整张图就是若干连通块(暂不考虑任意三点的条件
我们把连通块缩点,我们考虑任意两个极大连通块的关系,设块1位s1,块2为s2,假设现在加一条边使得,s1s2连通,则对于任意u∈s1,v∈s2,u和v的关系就确定下来了(假设在xy间加边,那么在s1s2中和xy相连的点都可以慢慢确定下来,已知2推1),换句话就是说,任意两个极大连通块间有两种连法,假设缩点后有m个块,那么答案就是2^(m-1)
接下来考虑维护这个边权01的正确性
考虑给每个点赋值,若边权为0,则u=0,v=0 / u=1,v=1,进一步边权则代表两点是否属于一类
我们用带权并查集维护集合内点与根是否属于一类,这个信息(0一类,1不是一类
输入的时候把边权反一下
假设我们现在要合并uv,若uv在同一集合内,显然uv与root组成的三元环异或值为0,如果不是则不合法
若不在一集合内,根据传递性,合并的时候,root_u -> u -> v -> root_v ,因为异或是无向的,所以root_u与root_v的新边的值就是uv和输入的边权z的异或和
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cstring>
#include<string>
#include<algorithm>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
#include<map>
#include<deque>
#include<set>
using namespace std;
typedef long long ll;
#define IOS ios::sync_with_stdio(false),cin.tie(0)
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pii pair<int ,int >
#define pb(v) push_back(v)
#define all(v) v.begin(),v.end()
#define int long long
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define endl "\\n"
#define fi first
#define se second
#define ls p<<1
#define rs p<<1|1
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define AC return 0
const int N=1e5+10;
const int mod=1e9+7;
const double eps=1e-8;
int n,m;
int fa[N],g[N];
int find(int x)
if( fa[x] == x) return x;
int t = find(fa[x]);
g[x] ^= g[fa[x]];
return fa[x] = t;
ll qsm(int a,int b )
int ans=1,temp=a;
while( b )
if( b&1 ) ans = (ans * temp )%mod;
temp = (temp * temp)%mod;
b>>=1;
return ans;
signed main()
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
IOS;
cin>>n>>m;
_for(i,1,n) fa[i]=i;
_for(i,1,m)
int x,y,z;cin>>x>>y>>z;
int fx = find(x);
int fy = find(y);
int temp = g[x]^g[y];
z^=1;
if( fx!=fy )
fa[fx] = fy;
g[fx] = g[x]^g[y]^z;
else//如果是一类,x,y,fy三元环异或为0
if( temp^z ) return cout<<0<<endl,0;
int tot=0;
_for(i,1,n)
if( i==find(i) ) tot++;
int ans = qsm(2,tot-1);
cout<<ans<<endl;
AC;
以上是关于CF553C Love Triangles(带权并查集)的主要内容,如果未能解决你的问题,请参考以下文章
cf Round #309 (Div. 2) E - Love Triangles(二分图染色)