选取不同列不同行的N个数。。。明摆着叫你二分匹配
二分答案,然后枚举边的范围并跑匈牙利,以此判断答案范围。
#include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <fstream> #include <iostream> #define rep(i, l, r) for(int i=l; i<=r; i++) #define down(i, l, r) for(int i=l; i>=r; i--) #define N 123 using namespace std; int read() { int x=0, f=1; char ch=getchar(); while (ch<‘0‘ || ch>‘9‘) { if (ch==‘-‘) f=-1; ch=getchar(); } while (ch>=‘0‘ && ch<=‘9‘) { x=x*10+ch-‘0‘; ch=getchar(); } return x*f; } int n, l, r, m, low, d[N][N], k[N]; bool b[N]; bool Find(int x) { rep(i, 1, n) if (d[x][i]>=low && d[x][i]<=low+m && !b[i]) { b[i]=1; if (!k[i] || Find(k[i])) { k[i]=x; return true; } } return false; } int main() { int t=read(); while (t--) { n=read(); rep(i, 1, n) rep(j, 1, n) d[i][j]=read(); int l=0, r=100; while (l!=r) { m=(l+r)/2; low=0; bool can=false; while (low+m<=100) { bool can2=true; rep(i, 1, n) k[i]=0; rep(i, 1, n) { rep(j, 1, n) b[j]=0; if (!Find(i)) { can2=false; break; } } if (can2) { can=true; break; } low++; } if (can) r=m; else l=m+1; } printf("%d\n", l); } return 0; }
时间: 2024-11-04 17:44:30