Kattis Problem - Elementary Math
题目类型:二分图最大匹配、匈牙利算法、离散化
题意
有 n 对整数,每对整数都可以使用 +、-、* 三种运算符进行运算。现在需要为每对整数选择一种运算符,并且保证最终 n 对整数的解都是不同的。
分析
对于每对数因为都有三种运算符,所以都有三个解,可以将每对数与它的解之间连一条边,则每对数与所有可能解构成一个二分图,然后就可以使用匈牙利算法来进行二分图的最大匹配。如果最后匹配了 n 个则说明存在解,然后根据匹配的结果输出每对数使用的运算符,否则无解。因为操作数比较大,所有要先离散化一下。
代码
static Node[] a;
static boolean[] vis;
static int[] match;
static int[] res;
static long[] all;
static int aLen;
public static void solve() throws IOException {
int n = nextInt();
init(n);
for (int i = 1; i <= n; i++) {
a[i] = new Node(nextInt(), nextInt());
all[aLen++] = a[i].add();
all[aLen++] = a[i].str();
all[aLen++] = a[i].mul();
}
unique();
for (int i = 1; i <= n; i++) {
a[i].to[0] = getAim(all, 1, aLen - 1, a[i].add());
a[i].to[1] = getAim(all, 1, aLen - 1, a[i].str());
a[i].to[2] = getAim(all, 1, aLen - 1, a[i].mul());
}
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j < aLen; j++) vis[j] = false;
if (Hungary(i)) ans++;
}
if (ans != n) pw.println("impossible");
else {
for (int i = 1; i <= n; i++) {
char op = '-';
if (all[res[i]] == a[i].add()) op = '+';
if (all[res[i]] == a[i].str()) op = '-';
if (all[res[i]] == a[i].mul()) op = '*';
pw.println(a[i].x + " " + op + " " + a[i].y + " = " + all[res[i]]);
}
}
}
public static boolean Hungary(int x) {
for (int i = 0; i < 3; i++) {
int e = a[x].to[i];
if (!vis[e]) {
vis[e] = true;
if (match[e] == 0 || Hungary(match[e])) {
match[e] = x;
res[x] = e;
return true;
}
}
}
return false;
}
public static int getAim(long[] a, int l, int r, long aim) {
while (l < r) {
int mid = l + r >> 1;
if (a[mid] >= aim) r = mid;
else l = mid + 1;
}
return r;
}
public static void unique() {
Arrays.sort(all, 1, aLen);
int q = 2, p = 2;
while (p < aLen) {
if (all[q - 1] != all[p]) all[q++] = all[p];
p++;
}
aLen = q;
}
public static void init(int n) {
a = new Node[n + 1];
res = new int[n * 3 + 1];
match = new int[n * 3 + 1];
vis = new boolean[n * 3 + 1];
all = new long[n * 3 + 1];
aLen = 1;
}
/*******************************************************************************************************************************/
static class Node {
int x, y;
int[] to;
public Node(int x, int y) {
// TODO Auto-generated constructor stub
this.x = x;
this.y = y;
to = new int[3];
}
public int add() { return x + y; }
public int str() { return x - y; }
public long mul() { return (long) x * y; }
}