QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#426412#6329. Colorful GraphEXODUSRE 0ms0kbC++175.7kb2024-05-31 10:17:102024-05-31 10:17:10

Judging History

你现在查看的是最新测评结果

  • [2024-05-31 10:17:10]
  • 评测
  • 测评结果:RE
  • 用时:0ms
  • 内存:0kb
  • [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

output:


result: