この記事では、数学オリンピックで出題された問題を競技プログラミングの形式に変換して紹介します(変換とは言ったものの、制約以外一切改変なしです)。実行時間とメモリの制限は2秒、1024MB程度を想定しています。
解説
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> iint;
// output
template<class T> ostream& operator<<(ostream &ostr, const vector<T> &vec){
int N = vec.size();
if(N == 0) return ostr;
ostr << vec[0];
for (int i = 1; i < N; i++) {
ostr << " " << vec[i];
}
return ostr;
}
int main(){
int N, M;
cin >> N >> M;
vector<vector<int>> G(N);
map<iint, int> mp;
for (int i = 0; i < M; i++) {
int u, v;
cin >> u >> v;
u--; v--;
if(u > v) swap(u, v);
G[v].push_back(u); // indexの大きい頂点からのみ参照
mp[{u, v}] = i; // 辺番号
}
vector<int> A(N, 1); // A_i
vector<int> B(M, 2); // B_i
vector<int> S(N, 1); // S_i
for (int i = 0; i < N; i++) {
for (int v : G[i]){
S[i] += 2;
S[v] += 2;
}
}
for (int i = 0; i < N; i++) {
int si = S[i];
int mins = si; // S_i を区間[mins, maxs]の整数から選べる
int maxs = si;
int k = G[i].size();
set<int> s;
for (int j = 0; j < k; j++) {
if(A[G[i][j]] == 1){
mins--;
}
else{
maxs++;
}
s.insert(S[G[i][j]]);
}
int news; // S_i を newsに変更する
for (int j = mins; j <= maxs; j++) {
if(!s.count(j)){
news = j;
break;
}
}
for (int j = 0; j < k; j++) {
if(A[G[i][j]] == 1){
if(news < S[i]){
A[G[i][j]] = 2;
B[mp[{G[i][j], i}]] = 1;
S[i]--;
}
}
else{
if(news > S[i]){
A[G[i][j]] = 1;
B[mp[{G[i][j], i}]] = 3;
S[i]++;
}
}
}
}
cout << A << endl;
cout << B << endl;
}