暑假集训Day8 A (拓扑排序判环)

原题链接在这里:Problem - A - Codeforces

首先还是判断是否有环,如果没有环的话直接输出1就行了,不得不说拓扑排序比tarjan判环的码量小了很多

然后就是一个环的性质,我们把环展成一条链,这链上面的点必定不是单调的,因为环必然会有一个点指向前面的点,所以这是显然的,根据这个性质对环的边进行染色就行了

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 const int MAX=5005;
 4 int n,m;
 5 struct Node{
 6     int v,no;
 7 }a[MAX][MAX];
 8 int cnt[MAX];
 9 int ii[MAX],ans[MAX];
10 bool topu(){
11     int i,j,zt,an=0;
12     queue <int> q;
13     while (!q.empty()) q.pop();
14     for (i=1;i<=n;i++)
15         if (ii[i]==0)
16             q.push(i),an++;
17     while (!q.empty()){
18         zt=q.front();q.pop();
19         //cout<<zt<<endl;
20         for (i=1;i<=cnt[zt];i++){
21             //cout<<zt<<' '<<a[zt][i].v<<endl;
22             if (ii[a[zt][i].v]){
23                 ii[a[zt][i].v]--;
24                 if (ii[a[zt][i].v]==0) q.push(a[zt][i].v),an++;
25             }
26         }
27     }
28     return (an==n);
29 }
30 int main(){
31     int i,j,u,v;
32     scanf("%d%d",&n,&m);
33     memset(cnt,0,sizeof(cnt));
34     memset(ii,0,sizeof(ii));
35     for (i=1;i<=m;i++){
36         scanf("%d%d",&u,&v);
37         a[u][++cnt[u]].v=v;
38         a[u][cnt[u]].no=i;
39         ii[v]++;
40     }
41     if (topu()){
42         printf("1\n");
43         for (i=1;i<=m;i++) printf("1 ");
44         return 0;
45     }
46     memset(ans,0,sizeof(ans));
47     for (i=1;i<=n;i++)
48         for (j=1;j<=cnt[i];j++)
49             if (!ans[a[i][j].no]){
50                 if (a[i][j].v<i) ans[a[i][j].no]=1;
51                 else ans[a[i][j].no]=2;
52             }
53     printf("2\n");
54     for (i=1;i<=m;i++) printf("%d ",ans[i]);
55     return 0;
56 }

 

上一篇:day8-字典和集合


下一篇:逐梦校友圈——冲刺day8