QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#98528 | #6329. Colorful Graph | tom0727 | TL | 2ms | 3752kb | C++14 | 6.4kb | 2023-04-19 07:44:16 | 2023-04-19 07:44:20 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
#if __cplusplus >= 201103L
struct pairhash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
template<class T, class U>
size_t operator() (const pair<T,U> &p) const {
static const uint64_t FIXED_RANDOM = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(p.first + FIXED_RANDOM) ^ splitmix64(p.second+ FIXED_RANDOM);
}
};
struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = (uint64_t)chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
inline int randint(int l, int r) {
return uniform_int_distribution<int>(l,r)(rng);
}
inline double randdouble(double l, double r) {
return uniform_real_distribution<double>(l,r)(rng);
}
#endif
#ifndef ONLINE_JUDGE
# define LOG(x) (cerr << #x << " = " << (x) << endl)
#else
# define LOG(x) 0
#endif
#define fastio ios::sync_with_stdio(false); cin.tie(0);
#define ll long long
#define ull unsigned long long
#define ll128 __int128_t
#define PI 3.14159265358979323846
#define abs(a) ((a>0)?a:-(a))
#define pii pair<int,int>
#define pll pair<ll,ll>
const long double pi = acos(-1.0);
const long double eps = (double)1e-8;
const int mod = 1e9+7;
template<class T>
T qpow(T a, int b) {
T res = 1;
while (b) {
if (b & 1) res *= a;
a *= a;
b >>= 1;
}
return res;
}
int norm(int x) {
if (x < 0) {
x += mod;
}
if (x >= mod) {
x -= mod;
}
return x;
}
struct Z {
int x;
Z(int x = 0) : x(norm(x)) {}
Z(ll x) : x(norm((int)(x % mod))) {}
int val() const {
return x;
}
Z operator-() const {
return Z(norm(mod - x));
}
Z inv() const {
assert(x != 0);
return qpow(*this, mod - 2);
}
Z &operator*=(const Z &rhs) {
x = (ll)(x) * rhs.x % mod;
return *this;
}
Z &operator+=(const Z &rhs) {
x = norm(x + rhs.x);
return *this;
}
Z &operator-=(const Z &rhs) {
x = norm(x - rhs.x);
return *this;
}
Z &operator/=(const Z &rhs) {
return *this *= rhs.inv();
}
friend Z operator*(const Z &lhs, const Z &rhs) {
Z res = lhs;
res *= rhs;
return res;
}
friend Z operator+(const Z &lhs, const Z &rhs) {
Z res = lhs;
res += rhs;
return res;
}
friend Z operator-(const Z &lhs, const Z &rhs) {
Z res = lhs;
res -= rhs;
return res;
}
friend Z operator/(const Z &lhs, const Z &rhs) {
Z res = lhs;
res /= rhs;
return res;
}
friend std::istream &operator>>(std::istream &is, Z &a) {
ll v;
is >> v;
a = Z(v);
return is;
}
friend std::ostream &operator<<(std::ostream &os, const Z &a) {
return os << a.val();
}
};
const int maxn = 7002;
const int maxm = 1e5+55;
int n, m;
vector<int> adj[maxn];
struct Tarjan {
int dfn[maxn], low[maxn], id, from[maxn], scc = 0, sz[maxn];
bool in[maxn]; // instack or not
int st[maxn], tail = -1;
void dfs(int u) {
in[u] = 1;
st[++tail] = u;
dfn[u] = low[u] = ++id;
for (int to : adj[u]) {
if (dfn[to] && in[to]) low[u] = min(low[u], dfn[to]); // 要记得在栈内
if (!dfn[to]) {
dfs(to);
low[u] = min(low[u], low[to]);
}
}
if (dfn[u] == low[u]) {
from[u] = ++scc;
sz[scc] = 1;
while (tail >= 0 && st[tail] != u) {
int cur = st[tail];
from[cur] = from[u];
sz[scc]++;
tail--;
in[cur] = 0; // 记得这里,将在栈中的标记去掉
}
tail--;
in[u] = 0; // 记得这里,将在栈中的标记去掉
}
}
// 跑tarjan
void solve() {
for (int i = 1; i <= n; i++) {
if (!dfn[i]) dfs(i);
}
}
} tj;
bitset<maxn> f[maxn];
pii ed[maxn];
int match[maxn], vis[maxn], id = 0;
bool dfs(int i) {
for (int j = f[i]._Find_first(); j < f[i].size(); j = f[i]._Find_next(j)) {
if (!f[i][j] || vis[j] == id) continue;
vis[j] = id;
if (!match[j] || dfs(match[j])) {
match[j] = i;
return 1;
}
}
return 0;
}
int color[maxn], pre[maxn], nxt[maxn], ans[maxn];
int main() {
fastio;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
int u, v; cin >> u >> v;
adj[u].push_back(v);
ed[i] = {u, v};
}
tj.solve();
for (int i = 1; i <= m; i++) {
int u = ed[i].first, v = ed[i].second;
int fu = tj.from[u], fv = tj.from[v];
if (fu == fv) continue;
f[fu][fv] = 1;
// printf("fu = %d, fv = %d\n",fu,fv);
}
int N = tj.scc;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= N; j++) {
if (f[j][i]) f[j] |= f[i];
}
}
// int ans = 0;
for (int i = 1; i <= N; i++) {
id++;
dfs(i);
}
int c = 0;
for (int i = 1; i <= N; i++) {
if (match[i]) {
nxt[match[i]] = i;
pre[i] = match[i];
}
}
for (int i = 1; i <= N; i++) {
if (!pre[i]) {
int j = i;
++c;
while (j) {
color[j] = c;
j = nxt[j];
}
}
}
for (int i = 1; i <= n; i++) {
ans[i] = color[tj.from[i]];
cout << ans[i] << " ";
}
// assert(c == ans);
cout << "\n";
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 2ms
memory: 3752kb
input:
5 5 1 4 2 3 1 3 2 5 5 1
output:
1 2 1 2 1
result:
ok AC
Test #2:
score: 0
Accepted
time: 0ms
memory: 3620kb
input:
5 7 1 2 2 1 4 3 5 1 5 4 4 1 4 5
output:
2 2 1 2 2
result:
ok AC
Test #3:
score: 0
Accepted
time: 0ms
memory: 3696kb
input:
8 6 6 1 3 4 3 6 2 3 4 1 6 4
output:
1 1 1 1 2 1 3 4
result:
ok AC
Test #4:
score: -100
Time Limit Exceeded
input:
7000 6999 4365 4296 2980 3141 6820 4995 4781 24 2416 5844 2940 2675 3293 2163 3853 5356 262 6706 1985 1497 5241 3803 353 1624 5838 4708 5452 3019 2029 6161 3849 4219 1095 1453 4268 4567 1184 1857 2911 3977 1662 2751 6353 6496 2002 6628 1407 4623 425 1331 4445 4277 1259 3165 4994 1044 2756 5788 5496 ...