题意
https://vjudge.net/problem/CodeForces-1217D
请给一个有向图着色,使得没有一个环只有一个颜色,您需要最小化使用颜色的数量。
思路
因为是有向图,每个环两个颜色就可以满足了。所以最大为2,最小为1。
法1 dfs:
用dfs判断有向图的环,每次把构成环的最后那条边染成2,其余染成1。
法2 拓扑排序:
容易发现,对于一个有向图,如果成环那么点的序号必不是单调的,因为最后的那个点又会连回起始点。
所以我们把u<v染成1,u>v染成2,然后拓扑排序判环,如果有环那么就输出染色方案,否则全输出1。
代码
法1:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=5e3+5; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) vector<int> g[N]; int e[N][N],vis[N],col[N],gg,in[N]; void dfs(int u) { int sz=g[u].size(); in[u]=1; for(int i=0;i<sz;i++) { int v=g[u][i]; if(!vis[v]) { vis[v]=1; col[e[u][v]]=1; dfs(v); } else if(in[v]) { col[e[u][v]]=2; gg=1; } else { col[e[u][v]]=1; } } in[u]=0; } int main() { std::ios::sync_with_stdio(false); int n,m; while(cin>>n>>m) { memset(vis,0,sizeof(vis)); for(int i=1;i<=m;i++) { int u,v; cin>>u>>v; g[u].push_back(v); e[u][v]=i; } gg=0; for(int i=1;i<=n;i++) { if(!vis[i]) { // col[i]=1; vis[i]=1; dfs(i); } } if(!gg) { cout<<1<<endl; for(int i=1;i<=m;i++) cout<<1<<" "; cout<<endl; } else { cout<<2<<endl; for(int i=1;i<=m;i++) cout<<col[i]<<" "; cout<<endl; } } return 0; }
法2:
#include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define ll long long const int N=200005; const int mod=1e9+7; const double eps=1e-8; const double PI = acos(-1.0); #define lowbit(x) (x&(-x)) vector<int> g[N]; int col[N],du[N]; int n,m; bool topo() { queue<int> q; for(int i=1; i<=n; i++) if(du[i]==0) q.push(i); int cnt=0; while(!q.empty()) { int t=q.front(); for(int i:g[t]) { du[i]--; if(du[i]==0) q.push(i); } cnt++; q.pop(); } if(cnt!=n) return false; return true; } int main() { std::ios::sync_with_stdio(false); cin>>n>>m; for(int i=1; i<=m; i++) { int u,v; cin>>u>>v; g[u].push_back(v); col[i]=(u<v); du[v]++; } if(topo()) { cout<<1<<endl; for(int i=1;i<=m;i++) cout<<1<<" "; cout<<endl; } else { cout<<2<<endl; for(int i=1;i<=m;i++) cout<<col[i]+1<<" "; cout<<endl; } return 0; }