Gym 101485E Elementary Math (离散 + 二分图匹配)

Problem E Elementary Math Time limit: 10 seconds

Example exam by Ellen Ellen is teaching elementary math to her students and the time for the final exam has come. The exam consists of n questions. In each question the students have to add (+), subtract (−) or multiply (∗) a pair of numbers. Ellen has already chosen the n pairs of numbers. All that remains is to decide for each pair which of the three possible operations the students should perform. To avoid students getting bored, Ellen wants to make sure that the n correct answers to her exam are all different. Please help Ellen finish constructing the exam by automating this task.

Input The input consists of: • one line with one integer n (1 ≤ n ≤ 2 500), the number of pairs of numbers; • n lines each with two integers a and b (−106 ≤ a, b ≤ 106 ), a pair of numbers used.

Output For each pair of numbers (a, b) in the same order as in the input, output a line containing a valid equation. Each equation should consist of five parts: a, one of the three operators, b, an equals sign (=), and the result of the expression. All the n expression results must be different. If there are multiple valid answers you may output any of them. If there is no valid answer, output a single line with the string “impossible” instead.

题意:给你一个数 N, 然后下面有 N 对数,每对数可以进行 + - * 操作,每对数选择一个结果,是不是存在每对数选择的结果都不一样。如果是,把每对数选择的结果写下来,并记录下是什么操作,如果不行,就输出 impossible。

思路: 这个题看着就是一个二分图匹配问题。如果能够匹配上 N 个,说明就行。

由于数很大,我们要离散化。

当然,这个是二分图匹配,我们也可以用 最大流 来做。

这个题我 WA 的原因是,最后判断输出的时候,条件没有写完全,

少写了 else , 有可能存在 两个数 的 ( 加 减  乘 ) 得出的结果是一样的,这样的情况我没有考虑。

#include <bits/stdc++.h>
using namespace std;
#define mem(x,v) memset(x,v,sizeof(x))
const int N = 10000;
struct edge{
    int v,next;
}ed[N];
int cnt = -1;
int head[N];
struct node{
    int a;
    long long b;
    bool operator < (const node &now) const {
        return b < now.b;
    }
}f[N];
int d[N],linker[N];
long long x[N],y[N];
long long c[N];
bool vis[N];
int n,t = 0;
void Add(int u, int v){
    cnt++;
    ed[cnt].next = head[u];
    head[u] = cnt;
    ed[cnt].v = v;
    return;
}

bool dfs(int u){
    for (int i = head[u]; i != -1; i = ed[i].next){
        int v = ed[i].v;
        if (!vis[v]){
            vis[v] = 1;
            if (linker[v] == -1 || dfs(linker[v])){
                linker[v] = u;
                return 1;
            }
        }
    }
    return 0;
}
int big_matching(){
    int ans = 0;
    mem(linker,-1);
    for (int i = 0; i <= t; i++){
        mem(vis,0);
        if (dfs(i)) ans++;
    }
    return ans;
}
int main() {
    scanf("%d",&n);
    for (int i = 0; i < n; i++){
        scanf("%I64d%I64d",&x[i],&y[i]);
        f[i*3+0].b = x[i] + y[i];
        f[i*3+1].b = x[i] - y[i];
        f[i*3+2].b = x[i] * y[i];
        f[i*3+0].a = i*3+0;
        f[i*3+1].a = i*3+1;
        f[i*3+2].a = i*3+2;
    }
    sort(f,f+3*n);
    //for (int i = 0;i < 3*n; i++)
      //  printf("%d %d\n",f[i].a, f[i].b);
    c[0] = f[0].b; //离散化之后的值向原来值得映射。
    d[f[0].a] = 0; //在原来的位置上放上离散化的值。
    for (int i = 1; i < 3 * n; i++){
        if (f[i].b != f[i - 1].b) {
            t++;
            c[t] = f[i].b;
        }
        d[f[i].a] = t;
    }
    //for (int i = 0; i < 3*n; i++)
//        printf("%d %d\n",d[i],c[d[i]]);
    mem(head,-1);
    for (int i = 0; i < 3 * n; i++){
        Add(d[i],i/3);
    }
    int Ans = big_matching();
   // cout<<Ans<<endl;
    if (Ans != n) printf("impossible\n"); else {
        for (int i = 0; i < n; i++){
            long long tt = c[linker[i]];
            printf("%I64d ",x[i]);
            if (x[i] + y[i] == tt) printf("+ "); else //少写了 else 一直 WA ,
            if (x[i] - y[i] == tt) printf("- "); else
            if (x[i] * y[i] == tt) printf("* ");
            printf("%I64d = %I64d\n",y[i],tt);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/kidsummer/article/details/81295452