果然我的图论做的还是太少了。。。
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。
对应序号与结果加边。
/*
还没做
*/