QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#426412 | #6329. Colorful Graph | EXODUS | RE | 0ms | 0kb | C++17 | 5.7kb | 2024-05-31 10:17:10 | 2024-05-31 10:17:10 |
answer
#include <vector>
#include <algorithm>
#include <cassert>
namespace exodus{
namespace internal{
class nothing{
public:
nothing(){}
friend nothing operator +(const nothing&,const nothing&){return nothing();}
};
}
template<class info=internal::nothing>
struct dsu{
public:
struct node{
public:
node(){anc=-1,siz=1,ifo=info();}
int anc,siz;
info ifo;
};
dsu():_n(0){}
explicit dsu(int n){
_n=n;node.resize(n);
for(int i=0;i<n;i++)
node[i].anc=i;
}
void build(int n){
_n=n;
node.clear();
node.resize(n);
for(int i=0;i<n;i++)
node[i].anc=i;
}
int find(int u){
assert(0<=u&&u<_n);
return __find(u);
}
void merge(int u,int v){
assert(0<=u&&u<_n);
assert(0<=v&&v<_n);
u=__find(u),v=__find(v);
if(node[u].siz<node[v].siz)std::swap(u,v);
node[v].anc=u;
node[u].ifo=node[u].ifo+node[v].ifo;
}
bool check(int u,int v){
assert(0<=u&&u<_n);
assert(0<=v&&v<_n);
u=__find(u),v=__find(v);
return u==v;
}
private:
int _n;
std::vector<node>node;
int __find(int u){
return u==node[u].anc?u:node[u].anc=__find(node[u].anc);
}
};
}
#include <algorithm>
#include <array>
#include <cassert>
#include <functional>
#include <numeric>
#include <queue>
#include <tuple>
#include <vector>
#include <iostream>
namespace exodus{
struct scc_graph{
public:
scc_graph(){n=0;}
explicit scc_graph(int _n){n=_n;g.resize(n);}
std::vector<std::pair<int,int>>edges(){return edge;}
std::pair<int,int>get_edge(int i){
assert(0<=i&&i<(int)edge.size());
return edge[i];
}
void add_edge(int u,int v){
assert(0<=u&&u<n);
assert(0<=v&&v<n);
g[u].emplace_back(v);
edge.emplace_back(u,v);
}
std::vector<std::vector<int>> scc(){
std::vector<int>dfn(n,0),low(n,0),stk,ins(n,0),col(n,-1);
int dfx=0,col_cnt=0;
stk.reserve(n);
std::function<void(int)>tarjan=[&](int u){
dfn[u]=low[u]=++dfx;ins[u]=true;stk.emplace_back(u);
for(auto v:g[u])
if(!dfn[v])tarjan(v),low[u]=std::min(low[u],low[v]);
else if(ins[v])low[u]=std::min(low[u],dfn[v]);
if(dfn[u]==low[u]){
while(u!=stk.back())col[stk.back()]=col_cnt,ins[stk.back()]=false,stk.pop_back();
col[stk.back()]=col_cnt,ins[stk.back()]=false,stk.pop_back();
++col_cnt;
}
};
for(int i=0;i<n;i++)
if(!dfn[i])
tarjan(i);
std::vector<std::vector<int>>res(col_cnt);
for(int i=0;i<n;i++)
res[col[i]].emplace_back(i);
return res;
}
private:
int n;
std::vector<std::vector<int>>g;
std::vector<std::pair<int,int>>edge;
};
}
#include<bits/stdc++.h>
using namespace std;
bitset<7000>bts[7000];
int main(){
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
cin.tie(nullptr)->sync_with_stdio(false);
int n,m;
cin>>n>>m;
vector<pair<int,int>>edge(m);
for(auto& [u,v]:edge)
cin>>u>>v,--u,--v;
exodus::scc_graph sccG(n);
for(auto [u,v]:edge)
sccG.add_edge(u,v);
auto scc=sccG.scc();
vector<int>col(n);
for(auto& vertex:scc){
static int colx=0;
for(auto& u:vertex){
col[u]=colx;
}
++colx;
}
int k=scc.size();
vector<vector<int>>g(k);
set<pair<int,int>>edge_vis;
for(auto [u,v]:edge){
if(col[u]==col[v])
continue;
if(edge_vis.count(make_pair(col[u],col[v])))
continue;
edge_vis.emplace(col[u],col[v]);
g[col[u]].emplace_back(col[v]);
}
vector<int>deg(k);
auto bfs=[&](int s){
static queue<int>q;
q.emplace(s);
bts[s].reset();
bts[s].set(s);
while(!q.empty()){
int u=q.front();
q.pop();
for(auto v:g[u]){
if(!bts[s].test(v)){
bts[s].set(v);
q.emplace(v);
}
}
}
};
for(int i=0;i<k;i++){
bfs(i);
bts[i].set(i,false);
deg[i]=bts[i].count();
}
int cnt=k;
vector<int>match(k);
vector<int>nxt(k,-1);
vector<int>used(k);
auto dfs=[&](auto self,int u)-> bool {
for(int v=bts[u]._Find_first();v<7000;v=bts[u]._Find_next(v)){
if(used[v]==0){
used[v]=1;
if(nxt[v]==-1||self(self,nxt[v])){
nxt[v]=u;
return true;
}
}
}
return false;
};
vector<int>ord(k);
iota(ord.begin(),ord.end(),0);
sort(ord.begin(),ord.end(),[&](int x,int y){
return deg[x]<deg[y];
});
// mt19937 seed(chrono::steady_clock::now().time_since_epoch().count());
// shuffle(ord.begin(),ord.end(),seed);
for(int i=0;i<k;i++){
fill(used.begin(),used.end(),0);
if(dfs(dfs,ord[i]))
cnt--;
}
#ifdef EXODUS
cerr<<cnt<<'\n';
#endif
exodus::dsu dsu(k);
for(int u=0;u<k;u++){
if(nxt[u]!=-1){
dsu.merge(u,nxt[u]);
}
}
vector<int>ans(k);
for(int i=0;i<k;i++){
static int colx=0;
if(dsu.find(i)==i){
ans[i]=++colx;
}
}
for(int i=0;i<k;i++){
ans[i]=ans[dsu.find(i)];
}
for(int i=0;i<n;i++)
cout<<ans[col[i]]<<' ';
cout<<'\n';
#ifdef EXODUS
cerr<<clock()<<'\n';
vector<vector<int>>_g(n);
vector<vector<int>>reach(n,vector<int>(n));
for(auto [u,v]:edge){
_g[u].emplace_back(v);
}
auto _bfs=[&](int s){
static queue<int>q;
q.emplace(s);
reach[s][s]=true;
while(!q.empty()){
int u=q.front();
q.pop();
for(auto v:_g[u]){
if(!reach[s][v]){
reach[s][v]=true;
q.emplace(v);
}
}
}
};
for(int i=0;i<n;i++)
_bfs(i);
// for(int i=0;i<n;i++,cerr<<'\n')
// for(int j=0;j<n;j++)
// cerr<<reach[i][j]<<' ';
vector<int>_lis;
for(int i=1;i<=cnt;i++){
_lis.clear();
for(int j=0;j<n;j++)
if(ans[col[j]]==i)
_lis.emplace_back(j);
for(auto u:_lis)
for(auto v:_lis){
if(!reach[u][v]&&!reach[v][u]){
cerr<<"Wrong Answer\n";
return 1;
}
}
}
cerr<<"Accept\n";
#endif
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 0
Dangerous Syscalls
input:
5 5 1 4 2 3 1 3 2 5 5 1