yuwj  

这个SB题才 2000?
是我对2000分rating 有什么误解吗?这玩意还要ECC来写
思路:
就是缩点,判环,奇环环长必须全部都是0,否则就是权值必须全部相等,偶数环,只有全部缺失值才会有 V 的贡献
要不是有ECC板子才不会尝试这题*

判断奇数环和值,dfs染色判断奇数环,并在过程中记录一个变量 val 判断就完了
代码:
`

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define all(v) v.begin(), v.end()
#define pb push_back
#define inf32 INT_MAX
#define inf64 LLONG_MAX
// #define int ll
typedef long long ll;
typedef unsigned long long ull;
typedef std::pair<int,int> pii;
mt19937_64 rng(time(0));
ll qmi(ll a, ll k, int m){ll res=1;while(k){if(k&1)res=res*a%m;a=a*a%m;k>>=1;}return res;}
const int Maxn = 2e5 + 10, Mod = 998244353;
int n,m,k,x,y,z,q,A,B, m1, m2, l, r,u,v, V;
string s,Map[Maxn];
vector<int> cnt, num, on, vis;
vector<pii> edges;
vector<vector<pii>> G;
//邻接表,点-边编号存图,得到缩点之后的树,每个点属于哪个连通分量
ll ans;

struct ECC{
    int n,cnt=0,tot=0;
    vector<int> dfn,low,bel, bridge;
    vector<vector<pair<int,int>>> g;
    vector<vector<int>> ecc,tree;
    stack<int> stk;

    ECC(){}
    ECC(int n,int m, vector<vector<pair<int,int>>> &G):n(n),ecc(n+5),dfn(n+5),low(n+5),bel(n+5), bridge(m+5){
        g = G;
        for(int i=1;i<=n;++i){
            if(!dfn[i]) {
                dfs(i,0);
                //建超级源点
                g[0].push_back({i,0});
                g[i].push_back({0,0});
            }
        }
        build();

        
    }

    //Targan dfs,栈存储边连通分量所有节点,分清树边和回边,如果dfn[id] == low[id] 这这是边连通分量的根节点
    void dfs(int u,int lid){
        dfn[u] = low[u] = ++ cnt;
        stk.push(u);

        for(auto [v,eid]: g[u]){
            //树边,没遍历过,用子树更新父亲
            if(!dfn[v]){
                dfs(v,eid);
                low[u]=min(low[u],low[v]);
                if(low[v] > dfn[u]) bridge[eid] = 1;
            }else if(eid != lid){ //回边,排除直接回到父节点的边
                low[u] = min(low[u], dfn[v]);
            }
        }

        //连通分量的根
        if(dfn[u]==low[u]){
            tot++;
            while(1){
                auto id = stk.top();stk.pop();
                bel[id] = tot, ecc[tot].push_back(id);
                if(id == u)break;
            }
        }
    }

    // 遍历原图边,若跨分量则连接一条树边,缩点建树了
    void build(){
        tree.resize(tot+5);
        for(int u=1;u<=n;++u){
            for(auto [v,e] : g[u]){
                if(bel[u] != bel[v])tree[bel[u]].push_back(bel[v]);
            }
        }
    }
};

ll work(){
    ECC Ecc(n,m,G);
    ll ans = 1, flg = 1;
    vector<int> col(n+1,-1); 
    For(i,1,n){
        if(col[i] != -1) continue;

        // dfs 在 ECC 上染色判断奇数环还是偶数环,
        // 然后判断值是否存在两个及以上
        int val = -1;
        auto dfs = [&](auto &&self, int u,int fa, int color) -> bool{
            col[u] = color;
            
            if(num[u] != -1){
                if(val == -1){
                    val = num[u];
                }else if(val != num[u]) flg = 0;
            }

            bool odd_circle = 0;
            for(auto [v,eid] : G[u]){
                // 桥,非同一环,回边
                if(Ecc.bridge[eid] || Ecc.bel[v] != Ecc.bel[i] || eid == fa) continue;
                
                if(col[v] == -1){ // 没涂色
                    odd_circle |= self(self, v, eid, color ^ 1);
                }else if(col[u] == col[v]){ // 下一个点涂色了,且和当前点颜色相等,就是奇数环
                    odd_circle = 1;
                }
            }

            return odd_circle;
        };

        if(dfs(dfs,i,0,0)){ // 奇数环,要么全部为 0, 全部值相等
            if(val != -1 && val != 0) flg = 0;
        }else if(val == -1){
            ans = ans * V % Mod;
        }

        if(!flg) return 0;
    }
    return ans;
    // return qmi(V,ans,Mod);
}

void init(){
    G.resize(n+5);
    For(i,1,n) G[i].clear();
    num.assign(n+1,0); edges.clear();
}

void solve(){
    cin >> n >> m >> V; init();
    For(i,1,n) cin >> num[i];
    For(i,1,m)cin >> x >> y, edges.emplace_back(x,y), G[x].pb({y,i}), G[y].pb({x,i});
    
    cout << work() << '\n';
}

int main() {
	ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	int t = 1;
	cin >> t;
	while (t -- ) {
		solve();
	}
	return 0;
}
`

参考:
https://www.cnblogs.com/maburb/p/19064356

posted on 2025-09-20 10:37  xiaowang524  阅读(6)  评论(0)    收藏  举报