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;
}
posted @ 2025-10-18 14:30  usedchang  阅读(1)  评论(0)    收藏  举报