CF2135 C. By the Assignment
C.By the Assignment
题意简述
给定一张无向图,每个点带有一个权值,要求图上任意两点之间的简单路径权值异或和相同,现在权值存在缺失,缺失的权值为-1,求补全图使之满足性质的方式有多少种?
解题思路
手玩两组样例,不难发现由于异或自反性的限制,可以把无向图分成若干个 "边双",满足某个边双中如果存在奇环则其一定权值得为0,如果不存在则这个边双权值处处相等。直接bcc把图分解为若干个边双,二分图染色判断环是否为奇环,然后利用乘法原理累乘就做完了。
AC code
//Stop learning useless algorithms, go and solve some problems, learn how to use binary search.
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
const int mod=998244353;
struct DECC{
vector< vector<pair<int,int> >>G;
vector< vector<int> >B;// 存储所有边双连通分量
vector<int>dfn,low;//时间戳
stack<int>st;
vector<char>vis;
vector<int>mp;// 每个点属于哪个分量
int cnt,n,id;
DECC(int n):n(n),cnt(0),id(0){
G.resize(n+1);
low.resize(n+1);
dfn.resize(n+1);
mp.resize(n+1);
}
void add(int x,int y){
++id;
G[x].push_back({y,id});
G[y].push_back({x,id});
}
void tarjan(int u,int fa){
dfn[u]=low[u]=(++cnt);
st.push(u);
for(auto &[v,id]:G[u]){
if(!dfn[v]){
tarjan(v,id);
low[u]=min(low[u],low[v]);
}
else if(id!=fa&&dfn[v]<dfn[u]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
vector<int>tmp;
int y;
do{
y=st.top();
mp[y]=B.size();
st.pop();
tmp.push_back(y);
}while(y!=u);
if(!tmp.empty()) B.push_back(tmp);
}
}
void run(){
for(int i=1;i<=n;i++){
if(!dfn[i]) tarjan(i,0);
}
}
};
void solve(){
int n,m;ll v;
cin>>n>>m>>v;
vector<int>a(n+1);
for(int i=1;i<=n;i++) cin>>a[i];
DECC decc(n+1);
for(int i=1;i<=m;i++){
int x,y;cin>>x>>y;
decc.add(x,y);
}
decc.run();
vector<int>col(n+1,-1);
auto bfs=[&](vector<int>&a) ->bool {
queue<int>Q;
Q.push(a.front());
col[a.front()]=0;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(auto &[v,id]:decc.G[u]){
if(decc.mp[v]!=decc.mp[u]) continue;
if(col[v]==-1){
Q.push(v);
col[v]=(col[u]^1);
}
else if(col[v]==col[u]) return false;
}
}
return true;
};
ll ans=1;
for(int i=0;i<decc.B.size();i++){
if(decc.B[i].front()>n) continue;
if(bfs(decc.B[i])) {
int val=-1;
for(int j=0;j<decc.B[i].size();j++){
int u=decc.B[i][j];
if(a[u]!=-1) {
val=a[u];
break;
}
}
for(int j=0;j<decc.B[i].size();j++){
int u=decc.B[i][j];
if(val!=a[u]&&a[u]!=-1){
cout<<0<<endl;
return;
}
a[u]=val;
}
if(val==-1) ans=ans*v%mod;
}
else{
for(int j=0;j<decc.B[i].size();j++){
int u=decc.B[i][j];
if(a[u]==-1) a[u]=0;
else if(a[u]!=0) {
cout<<0<<endl;
return;
}
}
}
}
cout<<ans<<endl;
}
int main(){
cin.tie(0)->ios::sync_with_stdio(false);
int T=1;cin>>T;
while(T--) solve();
return 0;
}