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;
}