题目链接:https://vjudge.net/contest/330119#problem/A
题目大意:
1.给出一张有向图,给该图涂色,要求同一个环里的边不可以全部都为同一种颜色。问最少需要多少颜色,并输出各边的涂色。
解题思路:
1.多画几张图就发现,颜色种类只会是1或者2。当不存在环的时候,全部涂1。当存在环的时候,环中可以分成两种边(小节点指向大节点涂1,大节点指向小节点涂2),就会发现所有的环颜色一定不会全部相同。
2.思考过1就发现这道题只需要判断是否存在环即可。可以用拓扑判断。原理为:在拓扑的过程中,入度为0的点会入队,但由于环上各点入度不可能为0.因此无法入队。所以在拓扑结束后,还存在没有入队的点,即存在环。

1 #include<stdio.h> 2 #include<string.h> 3 #include<queue> 4 #define mem(a, b) memset(a, b, sizeof(a)) 5 const int MAXN = 5100; 6 const int MAXM = 5100; 7 using namespace std; 8 9 int n, m; 10 int head[MAXN], cnt, in[MAXN], out[MAXN], tot; 11 queue<int> Q; 12 13 struct Edge 14 { 15 int from, to, next; 16 }edge[MAXM]; 17 18 void add(int a, int b) 19 { 20 cnt ++; 21 edge[cnt].from = a; 22 edge[cnt].to = b; 23 edge[cnt].next = head[a]; 24 head[a] = cnt; 25 } 26 27 int topo() 28 { 29 for(int i = 1; i <= n; i ++) 30 { 31 if(!in[i]) 32 { 33 Q.push(i); 34 tot ++; 35 } 36 } 37 while(!Q.empty()) 38 { 39 int temp = Q.front(); 40 Q.pop(); 41 for(int i = head[temp]; i != -1; i = edge[i].next) 42 { 43 int to = edge[i].to; 44 in[to] --; 45 if(!in[to]) 46 { 47 Q.push(to); 48 tot ++; 49 } 50 } 51 } 52 if(tot != n) //存在 点 没有入队 53 return 1; 54 else 55 return 0; 56 } 57 58 int main() 59 { 60 scanf("%d%d", &n, &m); 61 mem(head, -1); 62 for(int i = 1; i <= m; i ++) 63 { 64 int a, b; 65 scanf("%d%d", &a, &b); 66 in[b] ++, out[a] ++; 67 add(a, b); 68 } 69 if(topo()) //判是否有环存在 70 { 71 printf("2 "); 72 int flag = 1; 73 for(int i = 1; i <= cnt; i ++) 74 { 75 int a = edge[i].from, b = edge[i].to; 76 if(flag) 77 { 78 if(a < b) 79 printf("1"); 80 else 81 printf("2"); 82 flag = 0; 83 } 84 else 85 { 86 if(a < b) 87 printf(" 1"); 88 else 89 printf(" 2"); 90 } 91 } 92 printf(" "); 93 } 94 else 95 { 96 printf("1 1"); 97 for(int i = 1; i < m; i ++) 98 printf(" 1"); 99 printf(" "); 100 } 101 return 0; 102 }