果然我的图论做的还是太少了。。。
1. 二分图;
首先结果可能有负的, 所以+100, 所以结果的范围是 【0~10100】
将每个式子的序号看成一列, 将可能的结果(0到10100)看成一列, 将式子序号与该式子产生的四个结果加边。
跑出个二分图匹配, 匹配数等于n即可。。
#include <bits/stdc++.h>
#define ll long long
#define ms(x) memset(x, 0, sizeof(x))
#define inf 0x3f3f3f3f
#define mf(x) memset(x, inf, sizeof(x))
#define mf1(x) memset(x, -1, sizeof(x))
using namespace std;
const int N = 101;
const int M = 10103;
int uN, vN;
int g[N][M];
int a[N],b[N];
bool used[M];
int linker[M];
bool dfs(int u){
for(int v=0;v<=10100;v++){
if(g[u][v]&& !used[v]){
used[v] = true;
if(linker[v] == -1 || dfs(linker[v])){
linker[v] = u;
return true;
}
}
}
return false;
}
int hungary(){
int res = 0;
mf1(linker);
for(int u=0;u<uN;u++){
ms(used);
if(dfs(u)) res++;
}
if(res == uN) return 1;
else return 0;
}
void addedge(int i, int x){
g[i][x] = 1;
}
int main() {
// + 1 . - 2 . * 3 . / 4
scanf("%d", &uN);
for(int i=0;i<uN;i++){
scanf("%d%d", &a[i], &b[i]);
addedge(i, a[i]+b[i]+100);
addedge(i, a[i]-b[i]+100);
addedge(i, a[i]*b[i]+100);
addedge(i, a[i]/b[i]+100);
}
int ans = hungary();
if(!ans) puts("QAQ");
else{
puts("menhera");
for(int i=0;i<uN;i++){
for(int j=0;j<=10100;j++){
if(linker[j]==i){
if(a[i]+b[i]==j-100) printf("%d + %d = %d\n",a[i],b[i],j-100);
else if(a[i]-b[i]==j-100) printf("%d - %d = %d\n",a[i],b[i],j-100);
else if(a[i]*b[i]==j-100) printf("%d * %d = %d\n",a[i],b[i],j-100);
else if(a[i]/b[i]==j-100) printf("%d / %d = %d\n",a[i],b[i],j-100);
break;
}
}
}
}
return 0;
}
2. 网络流:
我觉得这个应该也挺好想的。。。
源点与序号(即式子)的边的容量为1;
结果与汇点的边的容量为1。
对应序号与结果加边。
/*
还没做
*/