結果
| 問題 |
No.416 旅行会社
|
| コンテスト | |
| ユーザー |
しらっ亭
|
| 提出日時 | 2016-08-28 00:47:09 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 309 ms / 4,000 ms |
| コード長 | 3,168 bytes |
| コンパイル時間 | 2,086 ms |
| コンパイル使用メモリ | 183,128 KB |
| 実行使用メモリ | 23,532 KB |
| 最終ジャッジ日時 | 2024-12-14 20:03:55 |
| 合計ジャッジ時間 | 6,353 ms |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 21 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
#define _p(...) (void)printf(__VA_ARGS__)
#define forr(x,arr) for(auto&& x:arr)
#define _overload3(_1,_2,_3,name,...) name
#define _rep2(i,n) _rep3(i,0,n)
#define _rep3(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload3(__VA_ARGS__,_rep3,_rep2,)(__VA_ARGS__)
#define _rrep2(i,n) _rrep3(i,0,n)
#define _rrep3(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define rrep(...) _overload3(__VA_ARGS__,_rrep3,_rrep2,)(__VA_ARGS__)
#define ALL(x) (x).begin(), (x).end()
#define BIT(n) (1LL<<(n))
#define SZ(x) ((int)(x).size())
#define fst first
#define snd second
typedef long long ll;
typedef vector<int> vi;typedef vector<vi> vvi;typedef pair<int,int> pii;typedef vector<pii> vpii;
vector<int> i2g; // i2g[i] := アイテム i の所属するグループの番号
vector<vector<int>> g2i; // g2i[g] := グループ g に所属するアイテムたち
void init(int n) {
i2g.resize(n);
g2i.resize(n);
for (int i = 0; i < n; ++i) {
// 最初はアイテム i はグループ i に所属
i2g[i] = i;
g2i[i].assign(1, i);
}
}
// アイテム ia の所属するグループとアイテム ib の所属するグループを 1 つにする
// (ia と ib は違うグループに所属するものとする)
void merge(int ia, int ib) {
// ia の所属するグループが ib の所属するグループより小さくならないようにする
if (g2i[i2g[ia]].size() < g2i[i2g[ib]].size()) {
swap(ia, ib);
}
int ga = i2g[ia], gb = i2g[ib];
if (ga == gb) return;
// グループ gb に所属する全てのアイテムをグループ ga に移す
for (int j : g2i[gb]) i2g[j] = ga;
g2i[ga].insert(g2i[ga].end(), g2i[gb].begin(), g2i[gb].end());
g2i[gb].clear();
}
// アイテム ia とアイテム ib は同じグループに所属しているか?
bool is_same_group(int ia, int ib) {
return i2g[ia] == i2g[ib];
}
void Main() {
int N, M, Q;
scanf("%d%d%d", &N, &M, &Q);
vpii bridges;
vpii breaks;
set<pii> break_set;
rep(i, M) {
int u, v;
scanf("%d%d", &u, &v);
u--; v--;
bridges.emplace_back(u, v);
}
rep(i, Q) {
int u, v;
scanf("%d%d", &u, &v);
u--; v--;
breaks.emplace_back(u, v);
break_set.emplace(u, v);
}
vi ans(N);
init(N);
// 壊れない橋を繋ぐ
forr(uv, bridges) {
if (!break_set.count(uv)) {
merge(uv.fst, uv.snd);
}
}
// 最初から到達できるやつ
rep(i, 1, N) {
if (is_same_group(0, i)) {
ans[i] = -1;
}
}
// 逆回し
rrep(i, Q) {
int c = breaks[i].fst;
int d = breaks[i].snd;
bool c0 = is_same_group(c, 0);
bool d0 = is_same_group(d, 0);
if (c0 && d0) {
// 何もしない
}
else {
if (c0) {
// D側の頂点が0と繋がるので答えを更新
forr(v, g2i[i2g[d]]) ans[v] = i+1;
}
else if (d0) {
// C側の頂点が0と繋がるので答えを更新
forr(v, g2i[i2g[c]]) ans[v] = i+1;
}
merge(c, d);
}
}
rep(i, 1, N) _p("%d\n", ans[i]);
}
int main() { cin.tie(0); ios::sync_with_stdio(false); Main(); return 0; }
しらっ亭