educational codeforces round 72 d. coloring edges(拓扑判环)

题意:现在有n个点,m条有向边,现在要对这m条有向边染色,要求是在一个环里面的边的颜色不能相同,

现在让你求出最少要几种颜色,才能满足条件的染色,并输出方案数

首先判断有无环,没环直接1,

有环的话,设计一种染色方案(差不多是个构造?CF里面好多方案不唯一的都要自己指定一种行之有效的方案出来)

考虑存在环的时候,必然既存在从小点指向大点的边,也存在从大点指向小点的边,对这两种边分别染色就可以保证环内颜色不同,

所以最多只需要两种颜色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

using namespace std;
#define endll 'n'
#define C getchar()
typedef long long ll;
#define pi acos(-1.0)
#define INF 0x3f3f3f3f
#define mod 1000000007
#define pii pair<int, int>
const int MAXN = 2e5 + 10;
#define stop system("pause")
#define lowbit(x) ((x) & (-x))
#define Temp template <typename T>
#define mem(a, b) memset(a, b, sizeof(a))
#define fast ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
Temp inline void (T &s)
{
s = 0;T t = 1, k = C;
for (; k < '0' || k > '9'; k = C)if (k == '-') t = -1;
for (; k >= '0' && k <= '9'; k = C) s = (s << 1) + (s << 3) + (k ^ 48);
s *= t;
}

int n,m;
int in[MAXN];
vector<int>mp[MAXN];
int topo()
{
queue<int>q;
for(int i=1;i<=n;i++) //n 节点的总数
if(in[i]==0) q.push(i); //将入度为0的点入队列
int k=0;
while(!q.empty())
{
int p=q.front(); q.pop(); // 选一个入度为0的点,出队列
k++;
for(int i=0;i<mp[p].size();i++)
{
int y=mp[p][i];
if((--in[y])==0) q.push(y);
}
}
if(k==n) return 1;//无环
else return 0;// ans 中的长度与n不相等,就说明无拓扑序列,有环
}

char ans[MAXN];
int main()
{
rd(n),rd(m);
for(int i=0;i<m;++i)
{
int u,v;rd(u),rd(v);
mp[u].push_back(v);
in[v]++;
if(u<v) ans[i]='1';
else ans[i]='2';
}
if(topo())
{
printf("1n");
for(int i=0;i<m;++i) printf("1 ");
cout<<endll;
}
else
{
printf("2n");
for(int i=0;i<m;++i) printf("%c ",ans[i]);
cout<<endll;
}
//stop;
return 0;
}