题意
存在两个点集
U,V
,点集
U
中的每个点均向
分析
注意到要构成完全二分图,即每个点要且仅被一条边所连接。所以考虑度数不确定的点集
V
,对于所有度数为1的点均是仅一种选择,小编采用搜索的方法对所有度数为1的点进行与确认,通过0,1交换的方式鉴别对应边是否肯定会被选中。递归的去除完所有度数为1的点后,剩下的部分必然组成
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 300300
#define eps 1e-7
#define lson rt<<1
#define rson rt<<1|1
#define LL long long
const int mod=998244353;
struct Edge{
int v;
LL w;
Edge(){}
Edge(int _v,LL _w):v(_v),w(_w){}
};
vector<Edge> edge;
vector<int> g[MAXN*2];
int deg[MAXN*2];
int vis[MAXN*2];
LL cnt[2];
LL ans;
void addedge(int u,int v,LL w){
g[u].push_back(edge.size());
edge.push_back(Edge(v,w));
deg[u]++;
}
void dfs(int u,int f,int flg){
vis[u]=1;
for(int i=0;i<g[u].size();++i){
Edge &e = edge[g[u][i]];
if(vis[e.v])
continue;
deg[e.v]--;
if(flg)
ans=(ans*e.w)%mod;
if(deg[e.v]==1)
dfs(e.v,u,1-flg);
}
}
void dfs2(int u,int f,int idx){
for(int i=0;i<g[u].size();++i){
Edge &e = edge[g[u][i]];
if(e.v==f || vis[e.v])
continue;
vis[e.v]=1;
cnt[idx]=(cnt[idx]*e.w)%mod;
dfs2(e.v,u,1-idx);
}
}
int main(){
int T,n,v;
LL w;
cin>>T;
while(T--){
scanf("%d",&n);
edge.clear();
memset(vis,0,sizeof(vis));
for(int i=1;i<=2*n;++i){
g[i].clear();
deg[i]=0;
}
for(int i=1;i<=n;++i){
for(int k=0;k<2;++k){
scanf("%d %I64d",&v,&w);
v+=n;
addedge(i,v,w);
addedge(v,i,w);
}
}
ans=1;
for(int i=n+1;i<=2*n;++i)
if(deg[i]==1)
dfs(i,0,1);
for(int i=1;i<=2*n;++i)
if(!vis[i]){
cnt[0]=cnt[1]=1;
dfs2(i,0,0);
ans=(ans*(cnt[0]+cnt[1]))%mod;
}
printf("%I64d\n",ans);
}
}