题意:有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. "); 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 "); 121 else if(!year[i] && !tag[i]) printf("B "); 122 else printf("C "); 123 } 124 return 0; 125 }