「真想待在你們的身邊
看著你們慢慢長大
雖然我不能算是個好媽媽
但我很慶幸能生下你們
還有呢
這句話一定要說出來才行
露比 阿奎亞
我愛你們
總算說出口了
對不起
這句話媽媽說得太晚了
太好了
這句話絕對
不是謊言...」
偶像星野愛死後 4 年,星野阿奎亞仍然在嘗試著破解母親當年的第三隻手機。
終於,有一天他成功了。
45510 — 那是手機登入的密碼,也是阿奎亞四年累積的心血。
接下來,他試著登入愛的社群帳號,可惜在科技日新月異的年代,區區的帳號密碼已經不夠安全。他需要向系統提交一種零知識證明(Zero Knowledge Proof),來確保他真的是星野愛本人。但是星野愛的手機過於老舊,以至於他需要自己寫一個程式去提交這個證明。
系統會根據使用者的密碼隨機構造一張有 $N$ 點 $M$ 邊的無向圖,而使用者需要提供一種對於這張圖的 3-著色。也就是說,使用者會給予每個點一個 $1$ 到 $3$ 之間的整數代表該點的顏色,使得對於任一條邊 $(u, v)$,$u$ 的顏色和 $v$ 的顏色都不同。
經過一些手段,阿奎亞獲取了系統用來生成無向圖的程式。
#include <bits/stdc++.h>
using namespace std;
unsigned int rng() {
static unsigned int secret_key = 45510; //使用者的密碼
secret_key *= 0xdefaced;
secret_key = (secret_key<<8) + (secret_key>>24) + 1;
return secret_key;
}
int main(int argc, char* argv[]) {
int cnt1 = atoi(argv[1]), cnt2 = atoi(argv[2]), cnt3 = atoi(argv[3]);
int m = atoi(argv[4]);
//產生一筆測資時,執行參數 argv 會被拿來執行 main
int n = cnt1 + cnt2 + cnt3;
cout << n << " " << m << "\n";
vector<pair<int, int>> edge;
for (int i = 0;i < m;i++) {
int type = rng()%3, u, v;
if (type == 0) u = rng()%cnt1, v = cnt1 + rng()%cnt2;
else if (type == 1) u = cnt1 + rng()%cnt2, v = cnt1+cnt2+rng()%cnt3;
else u = cnt1+cnt2+rng()%cnt3, v = rng()%cnt1;
if (rng()%2) swap(u, v);
edge.push_back({u, v});
}
vector<pair<int, int> > perm;
for (int i = 1;i <= n;i++) perm.push_back({rng(), i});
sort(perm.begin(), perm.end());
srand(time(NULL));
std::random_shuffle(edge.begin(), edge.end());
for (int i = 0;i < m;i++) {
cout << perm[edge[i].first].second << " " << perm[edge[i].second].second << "\n";
}
return 0;
}
請你幫阿奎亞寫一個程式,利用手機的密碼去破解這個問題。
輸入第一行有兩個整數 $N$, $M$,代表圖的點數和邊數。
接下來有 $M$ 行,第 $i$ 行有兩個整數 $u_i, v_i$,為第 $i$ 條邊的兩個端點。
保證所有測試資料都是按照題目敘述中的程式產生。
對於所有測試資料:
輸出 $N$ 個空白分隔的整數,第 $i$ 個數字為點 $i$ 的塗色。每個數字都必須是 ${1, 2, 3}$ 其中一者。
No. | Testdata Range | Constraints | Score |
---|---|---|---|
1 | 0~1 | 範例測資 | 0 |
2 | 0~23 | 無其他限制 | 100 |