题目链接:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1671 分析:把求值问题转化为二分答案之后的判定问题,判定时可以用网络流(没写过,不知道会不会TLE),或者用多重二分图匹配。 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define mp make_pair #define X first #define Y second #define MEMSET(a, b) memset(a, b, sizeof(a)) using namespace std; typedef unsigned int ui; typedef long long ll; typedef unsigned long long ull; typedef pair pii; typedef vector vi; typedef vi::iterator vi_it; typedef map mii; typedef priority_queue pqi; typedef priority_queue , greater > rpqi; typedef priority_queue pqp; typedef priority_queue , greater > rpqp; const int MAX_N = 1000 + 2; const int MAX_B = 20 + 2; int rank[MAX_N][MAX_B]; int cap[MAX_B]; int cnt[MAX_B][MAX_N]; bool vis[MAX_N]; bool graph[MAX_N][MAX_B]; int n, b; int dfs(int u) { for (int i = 1; i <= b; ++i) { if (!graph[u][i] || vis[i]) { continue; } vis[i] = true; if (cnt[i][0] < cap[i]) { cnt[i][++cnt[i][0]] = u; return 1; } for (int j = 1; j <= cnt[i][0]; ++j) { if (dfs(cnt[i][j])) { cnt[i][j] = u; return 1; } } } return 0; } int max_match() { int ret = 0, i; for (i = 1; i <= b; ++i) { cnt[i][0] = 0; } for (i = 1; i <= n; ++i) { MEMSET(vis, 0); ret += dfs(i); } return ret; } int main(int argc, char *argv[]) { // freopen("D:\\in.txt", "r", stdin); int i, j, k; cin >> n >> b; for (i = 1; i <= n; ++i) { for (j = 0; j < b; ++j) { scanf("%d", rank[i] + j); } } for (i = 1; i <= b; ++i) { scanf("%d", cap + i); } int low = 0, high = b - 1; while (low < high) { int mid = (low + high) >> 1; for (i = 0; i + mid < b; ++i) { MEMSET(graph, 0); for (j = 1; j <= n; ++j) { for (k = i; k <= i + mid; ++k) { graph[j][rank[j][k]] = true; } } if (max_match() == n) { break; } } if (i + mid < b) { high = mid; } else { low = mid + 1; } } cout << high + 1 << endl; return 0; }