先把所有可能的答案算出来,每个算式一个点,每个结果一个点,然后如果一个算式能算出一个结果,那么就连一条边
然后跑匈牙利,没有完美匹配就是impossible
每个算式最多有3个结果,所以边数是O(n)的,所以匈牙利的复杂度就是O(n^2)的
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <map>
#define ll long long
#define N 77777
#define M 77777
using namespace std;
inline int read(){
int ret=0;char ch=getchar();
bool flag=0;
while (ch<'0'||ch>'9'){
flag=ch=='-';
ch=getchar();
}
while ('0'<=ch&&ch<='9'){
ret=ret*10-48+ch;
ch=getchar();
}
return flag?-ret:ret;
}
struct edge{
int adj,next,op;
edge(){}
edge(int _adj,int _next,int _op):adj(_adj),next(_next),op(_op){}
} e[M];
int n,g[N],m;
void AddEdge(int u,int v,int op){
e[++m]=edge(v,g[u],op);g[u]=m;
}
int fx[N],fy[N],fop[N];
bool vis[N/3];
int dfs(int u){
if (vis[u]) return 0;
vis[u]=1;
for (int i=g[u];i;i=e[i].next){
int v=e[i].adj;
if (!fy[v]||dfs(fy[v])){
fy[v]=u;fx[u]=v;fop[u]=e[i].op;
return 1;
}
}
return 0;
}
char ch[3]={'+','-','*'};
inline ll calc(ll x,ll y,int op){
if (op==0) return x+y;
else if (op==1) return x-y;
else return x*y;
}
ll a[N],b[N];
map<ll,int> s;int cnt;
int main(){
n=read();
s.clear();
map<ll,int>::iterator it;
ll tmp;
for (int i=1;i<=n;++i){
a[i]=read();b[i]=read();
for (int op=0;op<3;++op){
it=s.find(calc(a[i],b[i],op));
if (it==s.end()) s.insert(make_pair(calc(a[i],b[i],op),++cnt));
AddEdge(i,s.find(calc(a[i],b[i],op))->second,op);
}
}
int tot=0;
memset(fx,0,sizeof(fx));
memset(fy,0,sizeof(fy));
for (int i=1;i<=n;++i)if (!fx[i]){
memset(vis,0,sizeof(vis));
tot+=dfs(i);
}
if (tot<n){puts("impossible");return 0;}
for (int i=1;i<=n;++i)
printf("%lld %c %lld = %lld
",a[i],ch[fop[i]],b[i],calc(a[i],b[i],fop[i]));
return 0;
}