結果
| 問題 |
No.3104 Simple Graph Problem
|
| コンテスト | |
| ユーザー |
shobonvip
|
| 提出日時 | 2025-01-29 04:08:54 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,118 bytes |
| コンパイル時間 | 2,984 ms |
| コンパイル使用メモリ | 213,456 KB |
| 実行使用メモリ | 77,548 KB |
| 最終ジャッジ日時 | 2025-01-31 23:34:02 |
| 合計ジャッジ時間 | 32,606 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 WA * 2 |
| other | AC * 18 WA * 32 RE * 15 |
ソースコード
#include<bits/stdc++.h>
using namespace std;
#include<atcoder/modint>
typedef atcoder::modint998244353 mint;
int main() {
int n, m; cin >> n >> m;
vector<mint> b(n);
for (int i=0; i<n; i++) {
int x; cin >> x;
b[i] = x;
}
vector<int> u(m), v(m);
vector ikeru(n, vector<pair<int,int>>(0));
for (int i=0; i<m; i++) {
cin >> u[i] >> v[i];
u[i]--; v[i]--;
ikeru[u[i]].push_back(pair(v[i], i));
ikeru[v[i]].push_back(pair(u[i], i));
}
vector<int> color(n);
bool is_bipartite = true;
vector<int> odd_cycle_edge_list;
vector<int> odd_cycle_vertex_list;
vector<bool> odd_cycle_vertex(n);
vector<bool> tansaku(n);
// 二部グラフ判定
auto dfs = [&](auto self, int i) -> int {
for (auto [j,e]: ikeru[i]) {
if (tansaku[j]) {
// 奇閉路が見つかったとき
if (color[i] == color[j]) {
is_bipartite = false;
odd_cycle_edge_list.push_back(e);
odd_cycle_vertex[i] = true;
odd_cycle_vertex_list.push_back(i);
return j;
}
}else{
tansaku[j] = true;
color[j] = color[i] ^ 1;
int v = self(self, j);
// 奇閉路の途中にいるとき
if (v >= 0) {
odd_cycle_edge_list.push_back(e);
odd_cycle_vertex[i] = true;
odd_cycle_vertex_list.push_back(i);
if (v == i) return -1;
return v;
}
}
if (!is_bipartite) {
return -1;
}
}
return -1;
};
tansaku[0] = true;
dfs(dfs, 0);
reverse(odd_cycle_edge_list.begin(), odd_cycle_edge_list.end());
reverse(odd_cycle_vertex_list.begin(), odd_cycle_vertex_list.end());
// 二部グラフである量が 0 でない -> ダメ
// ここは不要だが念のため
if (is_bipartite) {
mint total = 0;
for (int i=0; i<n; i++) {
if (color[i] == 0) total += b[i];
else total -= b[i];
}
if (total.val() != 0) {
cout << -1 << '\n';
return 0;
}
}
// 新しいグラフを作る
// 二部グラフ -> 全域木
// それ以外 -> 奇閉路を親にしたなもり全域グラフ
vector new_ikeru(n, vector<pair<int,int>>(0));
auto dfs2 = [&](auto self, int i) -> void {
for(auto [j,e]: ikeru[i]) {
if (tansaku[j]) continue;
if (odd_cycle_vertex[j]) continue;
tansaku[j] = 1;
new_ikeru[i].push_back(pair(j, e));
new_ikeru[j].push_back(pair(i, e));
self(self, j);
}
};
fill(tansaku.begin(), tansaku.end(), false);
if (is_bipartite) {
tansaku[0] = true;
dfs2(dfs2, 0);
}else{
for (int i: odd_cycle_edge_list) {
new_ikeru[u[i]].push_back(pair(v[i], i));
new_ikeru[v[i]].push_back(pair(u[i], i));
}
for (int i: odd_cycle_vertex_list) {
assert(!tansaku[i]);
tansaku[i] = true;
dfs2(dfs2, i);
}
}
// なもりグラフのように……
// ただし o-o この場合には注意する. これも見る必要がある.
vector<int> deg(n);
for (int i=0; i<n; i++) {
deg[i] = (int)new_ikeru[i].size();
}
vector<int> mada;
for (int i=0; i<n; i++) {
assert(deg[i] != 0);
if (deg[i] == 1) {
mada.push_back(i);
}
}
fill(tansaku.begin(), tansaku.end(), false);
vector<mint> ans(m);
while(!mada.empty()) {
int i = mada.back();
mada.pop_back();
tansaku[i] = true;
for (auto [j,e]: new_ikeru[i]) {
if (tansaku[j]) continue;
ans[e] = b[i];
b[i] -= ans[e];
b[j] -= ans[e];
deg[j] -= 1;
if (deg[j] == 1) {
mada.push_back(j);
}
}
}
if (!is_bipartite) {
int k = (int)odd_cycle_edge_list.size();
mint total_weight = 0;
for (int i: odd_cycle_vertex_list){
total_weight += b[i];
}
total_weight *= mint(2).inv();
{
int e = odd_cycle_edge_list[0];
ans[e] = total_weight;
for (int i=2; i<k; i+=2) {
int x = odd_cycle_vertex_list[i];
ans[e] -= b[x];
}
}
for (int i=1; i<k; i++) {
int x = odd_cycle_vertex_list[i];
int e = odd_cycle_edge_list[i];
int eprev = odd_cycle_edge_list[i-1];
ans[e] = b[x] - ans[eprev];
}
for (int i=0; i<k; i++) {
b[i] -= ans[odd_cycle_edge_list[i]];
b[(i+1)%k] -= ans[odd_cycle_edge_list[i]];
}
}
for (int i=0; i<n; i++) {
assert(b[i].val() == 0);
}
for (int i=0; i<m; i++) {
cout << i+1 << ' ' << ans[i].val() << endl;
}
}
shobonvip