题意:
给定n个正整数与a,b两个集合,求一种方案使得这n个数恰好被分在这两个集合中且集合中无多余的数且若x在a中则A-x在a中,若x在b中则B-x在b中。
题意理解了我好半天...
解法1:并查集。
把x, A - x,B - x(如果不存在B - x,x就不能放B集合)放入同一个并查集即可。
实现时注意一些乱七八糟的东西,大力讨论即可。
1 #include <cstdio> 2 #include <map> 3 #include <cstring> 4 const int N = 100010; 5 6 int a[N], ans[N], A, B, n, fa[N]; 7 std::map<int, int> mp; 8 9 inline int find(int x) { 10 if(x == fa[x]) { 11 return x; 12 } 13 return fa[x] = find(fa[x]); 14 } 15 inline bool check(int x, int y) { 16 return find(x) == find(y); 17 } 18 inline void merge(int x, int y) { 19 fa[find(x)] = find(y); 20 return; 21 } 22 23 24 int main() { 25 memset(ans, -1, sizeof(ans)); 26 for(int i = 1; i < N; i++) { 27 fa[i] = i; 28 } 29 scanf("%d%d%d", &n, &A, &B); 30 for(int i = 1; i <= n; i++) { 31 scanf("%d", &a[i]); 32 mp[a[i]] = i; 33 } 34 for(int i = 1; i <= n; i++) { 35 bool x = mp.find(A - a[i]) == mp.end(); 36 bool y = mp.find(B - a[i]) == mp.end(); 37 if(x && y) { 38 printf("NO"); 39 return 0; 40 } 41 else if(x) { 42 int &t = ans[mp[B - a[i]]]; 43 if(t == 0) { 44 printf("NO"); 45 return 0; 46 } 47 if(t == -1) { 48 t = 1; 49 } 50 ans[i] = 1; 51 merge(i, mp[B - a[i]]); 52 } 53 else if(y) { 54 int &t = ans[mp[A - a[i]]]; 55 if(t == 1) { 56 printf("NO"); 57 return 0; 58 } 59 if(t == -1) { 60 t = 0; 61 } 62 ans[i] = 0; 63 merge(i, mp[A - a[i]]); 64 } 65 else { 66 merge(i, mp[A - a[i]]); 67 merge(i, mp[B - a[i]]); 68 } 69 } 70 71 for(int i = 1; i <= n; i++) { 72 if(ans[i] == -1) { 73 ans[i] = ans[find(i)]; 74 } 75 else { 76 if(ans[find(i)] == -1) { 77 ans[find(i)] = ans[i]; 78 } 79 else if(ans[find(i)] != ans[i]) { 80 printf("NO"); 81 return 0; 82 } 83 } 84 } 85 printf("YES "); 86 for(int i = 1; i <= n; i++) { 87 if(ans[find(i)] == -1) { 88 printf("0 "); 89 } 90 else { 91 printf("%d ", ans[find(i)]); 92 } 93 } 94 95 return 0; 96 }