UVA1391/LA3713 Astronauts

题意:有A、B、C3个任务分配给n个宇航员,其中每个宇航员恰好分配一个任务。假设n个宇航员的平均年龄为x,只有年龄大于x的才能领取A任务;只有年龄严格小于x的才能领取B任务,而任务C没有限制。有m对宇航员相互讨厌,因此不能分配同一任务。求出是否能找出符合的任务方案。(转自http://blog.csdn.net/u011345461/article/details/39779721)

 

题目看上去是ABC三个选择,实际上每个人只有两个选择。对于每对矛盾,如果两个人选择相同(即均为BC或均为AC),那么一个选C另一个必选B(A),另一个选C一个必选B(A),一个选B(A)另一个必选C,另一个选B(A)一个必选C;如果两个人选择不同(一个AC一个BC),那么一个选C另一个必选B,另一个选C一个必选A。

这题数据范围很大,好奇nm做法是怎么水过去的。。

正解是tarjan缩点,标记每个块的对立块,建立反图,对反图top排序,对于当前的块x,删除对立块和对立块在反图上的出边,并把当前快入队。最后看队列里没被删除的块即为答案块。把点扫一扫看看在不在答案块,在的话这个点的值代表选A(B)还是选C就是这个人的选择

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #include <map>
  9 #include <string> 
 10 #include <cmath> 
 11 #define min(a, b) ((a) < (b) ? (a) : (b))
 12 #define max(a, b) ((a) > (b) ? (a) : (b))
 13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 14 template<class T>
 15 inline void swap(T &a, T &b)
 16 {
 17     T tmp = a;a = b;b = tmp;
 18 }
 19 inline void read(int &x)
 20 {
 21     x = 0;char ch = getchar(), c = ch;
 22     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 23     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 24     if(c == '-') x = -x;
 25 }
 26 const int INF = 0x3f3f3f3f;
 27 const int MAXN = 300000 + 10;
 28 struct Edge
 29 {
 30     int u,v,nxt;
 31     Edge(int _u, int _v, int _nxt){u = _u;v = _v;nxt = _nxt;}
 32     Edge(){}
 33 }edge1[MAXN << 3], edge2[MAXN << 3];
 34 int head1[MAXN], head2[MAXN], vis[MAXN], tag[MAXN], rebelong[MAXN], del[MAXN], q[MAXN], he, ta, indeg[MAXN], cnt1, cnt2, n, m, belong[MAXN], group, b[MAXN], bb[MAXN], dfn[MAXN], stack[MAXN], top, low[MAXN], dfst, year[MAXN], x, tmp1, tmp2;
 35 inline void insert1(int a, int b){edge1[++ cnt1] = Edge(a, b, head1[a]), head1[a] = cnt1;}
 36 inline void insert2(int a, int b){edge2[++ cnt2] = Edge(a, b, head2[a]), head2[a] = cnt2;}
 37 void dfs(int u)
 38 {
 39     b[u] = bb[u] = 1, dfn[u] = low[u] = ++ dfst, stack[++ top] = u;
 40     for(int pos = head1[u];pos;pos = edge1[pos].nxt)
 41     {
 42         int v = edge1[pos].v;
 43         if(!b[v]) dfs(v), low[u] = min(low[u], low[v]);
 44         else if(bb[v]) low[u] = min(low[u], dfn[v]); 
 45     }
 46     if(low[u] == dfn[u])
 47     {
 48         int now = -1;++ group;
 49         while(now != u) now = stack[top --], bb[now] = 0, belong[now] = group;
 50     }
 51 } 
 52 void rebuild()
 53 {
 54     memset(indeg, 0, sizeof(indeg)), memset(head2, 0, sizeof(head2));
 55     for(int i = 1;i <= cnt1;++ i)
 56         if(belong[edge1[i].u] != belong[edge1[i].v])
 57             insert2(belong[edge1[i].v], belong[edge1[i].u]), ++ indeg[belong[edge1[i].u]];
 58 }
 59 void tarjan()
 60 {
 61     memset(belong, 0, sizeof(belong)), memset(dfn, 0, sizeof(dfn)), memset(low, 0, sizeof(low)), group = 0, memset(b, 0, sizeof(b)), memset(bb, 0, sizeof(bb)), dfst = 0, top = 0, memset(rebelong, 0, sizeof(rebelong));
 62     for(int i = 1;i <= n;++ i) if(!b[i << 1]) dfs(i << 1);
 63     for(int i = 1;i <= n;++ i) if(!b[i << 1 | 1]) dfs(i << 1 | 1);
 64     for(int i = 1;i <= n;++ i) rebelong[belong[i << 1]] = belong[i << 1 | 1], rebelong[belong[i << 1 | 1]] = belong[i << 1];
 65     rebuild();
 66 }
 67 void top_sort()
 68 {
 69     he = 0, ta = 0, memset(del, 0, sizeof(del));
 70     for(int i = 1;i <= group;++ i) if(!indeg[i]) q[ta ++] = i;
 71     while(he < ta)
 72     {
 73         int now = q[he ++], renow = rebelong[now];
 74         if(del[now]) continue; del[renow] = 1;
 75         for(int pos = head2[renow];pos;pos = edge2[pos].nxt)
 76         {
 77             int v = edge2[pos].v;
 78             del[v] = 1;
 79             for(int poss = head2[v];poss;poss = edge2[poss].nxt) -- indeg[edge2[poss].v];
 80         }
 81         for(int pos = head2[now];pos;pos = edge2[pos].nxt) 
 82         {
 83             int v = edge2[pos].v;
 84             if(del[v]) continue;
 85             -- indeg[v];
 86             if(!indeg[v]) q[ta ++] = v;
 87         }
 88     }
 89 }
 90 int main()
 91 {
 92     while(scanf("%d %d", &n, &m) != EOF && n && m)
 93     {
 94         cnt1 = 0, memset(head1, 0, sizeof(head1)), x = 0;
 95         for(int i = 1;i <= n;++ i) read(year[i]), x += year[i];
 96         if(x % n == 0) x = x / n;
 97         else x = x / n + 1;
 98         for(int i = 1;i <= n;++ i) year[i] = year[i] >= x;  //year[i] = 1 表示选A或C  year[i] = 0 表示选B或C 
 99         for(int i = 1;i <= m;++ i)
100         {
101             read(tmp1), read(tmp2);
102             if(year[tmp1] == year[tmp2]) insert1(tmp1 << 1 | 1, tmp2 << 1), insert1(tmp2 << 1 | 1, tmp1 << 1), insert1(tmp1 << 1, tmp2 << 1 | 1), insert1(tmp2 << 1, tmp1 << 1 | 1);
103             else insert1(tmp1 << 1 | 1, tmp2 << 1), insert1(tmp2 << 1 | 1, tmp1 << 1); 
104         }
105         tarjan();
106         int flag = 0;
107         for(int i = 1;i <= n;++ i) if(belong[i << 1 | 1] == belong[i << 1]) flag = 1;
108         if(flag)
109         {
110             printf("No solution.\n");
111             continue;
112         }
113         top_sort(); 
114         memset(vis, 0, sizeof(vis)), memset(tag, 0, sizeof(tag));
115         for(int i = 0;i < ta;++ i) if(!del[q[i]]) vis[q[i]] = 1;
116         for(int i = 1;i <= n;++ i) 
117             if(vis[belong[i << 1]]) tag[i] = 0;
118             else tag[i] = 1;
119         for(int i = 1;i <= n;++ i)
120             if(year[i] && !tag[i]) printf("A\n");
121             else if(!year[i] && !tag[i]) printf("B\n");
122             else printf("C\n");
123     }
124     return 0;
125 }
UVA1391/LA3713

 

posted @ 2018-01-31 16:34  嘒彼小星  阅读(270)  评论(0编辑  收藏  举报