CERC 2012 J (拓扑排序)

题意:一些具有拓扑序的节点需要染色,这些节点一共分为两类。问你按照给出的拓扑顺序染色完结点最少需要多少次切换。

思路:我们按照拓扑排序的做法,建立两个栈分别存放两种不同种类的节点,每次把一个栈中的所有节点都处理完了才处理另一个,这样切换次数即为最终答案。

代码如下:

  1 /**************************************************
  2  * Author     : xiaohao Z
  3  * Blog     : http://www.cnblogs.com/shu-xiaohao/
  4  * Last modified : 2014-06-30 12:30
  5  * Filename     : cerc_j.cpp
  6  * Description     : 
  7  * ************************************************/
  8 
  9 #include <iostream>
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <cmath>
 14 #include <algorithm>
 15 #include <queue>
 16 #include <stack>
 17 #include <vector>
 18 #include <set>
 19 #include <map>
 20 #define MP(a, b) make_pair(a, b)
 21 #define PB(a) push_back(a)
 22 
 23 using namespace std;
 24 typedef long long ll;
 25 typedef pair<int, int> pii;
 26 typedef pair<unsigned int,unsigned int> puu;
 27 typedef pair<int, double> pid;
 28 typedef pair<ll, int> pli;
 29 typedef pair<int, ll> pil;
 30 
 31 const int INF = 0x3f3f3f3f;
 32 const double eps = 1E-6;
 33 const int LEN = 100000+10;
 34 int n, m, vex[LEN], ind[LEN], tmp_ind[LEN];
 35 bool vis[LEN];
 36 struct E{
 37     int to, next;
 38 }edge[LEN*10];
 39 int head[LEN], top;
 40 
 41 void init(){
 42     top = 0;
 43     memset(head, -1, sizeof head);
 44 }
 45 
 46 void addedge(int u, int v){
 47     edge[top].next = head[u];
 48     edge[top].to = v;
 49     head[u] = top++;
 50 }
 51 
 52 int solve(int flag){
 53     for(int i=0; i<n; i++)
 54         ind[i] = tmp_ind[i];
 55     memset(vis, 0, sizeof vis);
 56     queue<int> q1, q0;
 57     for(int i=0; i<n; i++){
 58         if(!ind[i]){
 59             vis[i] = 1;
 60             if(!vex[i]) q0.push(i);
 61             else q1.push(i);
 62         }
 63     }
 64     int ret = 0, cnt = 0;
 65     for(;;ret++){
 66         if(flag){
 67             if(q1.empty()) {
 68                 ret--; break;
 69             }
 70             while(!q1.empty()){
 71                 int nv = q1.front(); q1.pop();
 72                 cnt ++;
 73                 for(int i=head[nv]; i!=-1; i=edge[i].next){
 74                     int nx = edge[i].to;
 75                     ind[nx] --;
 76                     if(!ind[nx] && !vis[nx]){
 77                         vis[nx] = 1;
 78                         if(vex[nx]) q1.push(nx);
 79                         else q0.push(nx);
 80                     }
 81                 }
 82             }
 83         }else{
 84             if(q0.empty()) {
 85                 ret--; break;
 86             }
 87             while(!q0.empty()){
 88                 int nv = q0.front(); q0.pop();
 89                 cnt ++;
 90                 for(int i=head[nv]; i!=-1; i=edge[i].next){
 91                     int nx = edge[i].to;
 92                     ind[nx] --;
 93                     if(!ind[nx] && !vis[nx]){
 94                         vis[nx] = 1;
 95                         if(vex[nx]) q1.push(nx);
 96                         else q0.push(nx);
 97                     }
 98                 }
 99             }
100         }
101         flag = !flag;
102     }
103     if(cnt != n) return INF;
104     return ret;
105 }
106 
107 int main()
108 {
109 //    freopen("in.txt", "r", stdin);
110 
111     int a, b, T;
112     scanf("%d", &T);
113     while(T--){
114         init();
115         memset(tmp_ind, 0, sizeof tmp_ind);
116         scanf("%d%d", &n, &m);
117         for(int i=0; i<n; i++){
118             scanf("%d", &vex[i]);
119             vex[i] --;
120         }
121         for(int i=0; i<m; i++){
122             scanf("%d%d", &a, &b);
123             a--, b--;
124             addedge(a, b);
125             tmp_ind[b] ++;
126         }
127         int ans = min(solve(0), solve(1));
128         printf("%d\n", ans);
129     }
130     return 0;
131 }
View Code

 

posted @ 2014-07-01 14:54  张小豪  阅读(239)  评论(0编辑  收藏  举报