日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客网 【每日一题】4月23日题目精讲 边的染色

發布時間:2023/12/3 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客网 【每日一题】4月23日题目精讲 边的染色 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

鏈接:

時間限制:C/C++ 1秒,其他語言2秒 空間限制:C/C++ 32768K,其他語言65536K 64bit IO Format: %lld

題目描述

小團有一張n個點,m條邊的無向圖G,有些邊上已經被標記了0或1,表示它的邊權。 現在你需要給剩下的邊標記邊權為0或1,求有幾種標記的方式滿足: 對于G中任意一個環,里面所有邊的邊權的異或值為0。 環的定義如下: 對于任意k(k≥2)個點{a1,a2,...,ak},若對于所有的i<k滿足ai與ai+1之間有邊,且a1=ak成立,則這k個點構成一個環。

輸入描述:

第一行兩個整數n, m。

接下來m行,每行3個整數u, v, w,表示有一條邊(u,v),若w=-1則這條邊上沒有標記,否則w=0或1表示這條邊上標記了w。

數據保證沒有重邊和自環。

1≤n≤100,000 0≤m≤min(n*(n-1)/2, 100000)

輸出描述:

輸出方案數對998,244,353取模的值。

示例1
輸入
3 3
1 2 -1
2 3 -1
3 1 -1
輸出
4

題解:

看了鄧老師的題解,恍然大悟,感謝大佬講解
一下為我結合鄧老師所理解的:
首先思考:一個連通圖(圖中任意兩點都是連通的),給邊標上0和1,使得任意一個環的所有邊的異或和為0,問有多少種方案?

異或:相同為0,不同為1

題目要求我們給邊賦值,但是邊賦值很不方便,我們就看看選擇給點賦值,為什么?因為邊和點是共存的,特別是在一個環中,每個點都貢獻了兩個邊,那我們就可以把這個邊的值當做是邊兩端頂點的值的異或,一個環有m個點,m條邊,異或m條邊就等于將m個點都異或兩次。相同為0,那么異或兩次相同的值結果一定為0.那點就可以隨意賦值

對于一個連通塊:
將所有點的數都 ^ 1(也就是0變成1,1變成0),兩點異或出來的邊值并未發生改變(就相當于原本1 ^ 1 改成0 ^ 0,結果不變),n個點每個點都是有兩個方案的(即0或1),那么給點賦值的方案也就是2n個,對應的邊賦值方案是點的方案除以2,所以n個點的連通圖有2n-1種方案。

對于不是一個連通圖:
我們可以求分散的每個連通圖種類,然后乘一起就可

但是原本題目中是存在有些邊一開始就賦好值,我們可以從提前標好的邊開始出發找連通塊,不然到最后你自己標記的很有可能和題目給你不適配,又要重新改。在存有題目給的邊的這個連通塊里,我們只需要確定一個點的權值,其他部分也可以因此確定。如果把這個連通塊大小記作ki,那么這個連通塊的存在就會使得方案數需要在原來的基礎上(不考慮之前有標記)除以2 ki-1,因為其他點不能自由選。

還有:題目給你的數據本身可能就是矛盾,判定遠直接輸出0
我盡量只能理解到這份上。。

借鑒其他大佬的代碼:

#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 3; const int mod = 998244353; int f[maxn], col[maxn]; vector<pair<int,int> > edge[maxn]; bool flag; int find(int x){return f[x] == x ? x : f[x] = find(f[x]); } void dfs(int u, int p){//染色過程if (!flag) return;for (int i = 0; i < edge[u].size(); ++i){int v = edge[u][i].first, w = edge[u][i].second;if (col[v] == -1){col[v] = col[u]^w;dfs(v, u);}else if (col[u]^col[v] != w){flag = 0;return;}} } int main(void){int n, m,ans; int u, v, w;scanf("%d%d",&n,&m);for (int i = 1; i <= n; ++i) f[i] = i;ans = n;for (int i = 1; i <= m; ++i){cin >> u >> v >> w;if (find(u) != find(v)){ans--;f[find(u)] = find(v);/}if (w != -1){edge[u].push_back(make_pair(v, w));edge[v].push_back(make_pair(u, w));}}memset(col, -1, sizeof col);int cnt = 0;flag = 1;for (int i = 1; i <= n; ++i){if (col[i] == -1){col[i] = 0;dfs(i, i);cnt++;}}if (!flag){cout << 0 << endl; return 0;}ll ans = 1;for (int i = 0; i < cnt-ans; ++i) ans = ans*2%mod;cout << ans << endl;return 0; }

總結

以上是生活随笔為你收集整理的牛客网 【每日一题】4月23日题目精讲 边的染色的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。