HDU 4975 A simple Gaussian elimination problem. 네트워크 흐름 + 행렬의 dp
hdu4888과 같은 뜻으로 먼저 인터넷 흐름을 달리고 dp판은 가능하다.
==n^3의 dp는 넘을 수 없기 때문에 n을 200으로 변경합니다.
= 출제자가 다해의 경우를 200*200 이외의 행렬에 두지 않았기 때문이다.
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX_N = 1207;
const int MAX_E = MAX_N * MAX_N * 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int v, nxt;
long long cap;
Edge() {
}
Edge(int _v, int _nxt, long long _cap) {
v = _v, nxt = _nxt, cap = _cap;
}
};
Edge G[MAX_E];
int edgecnt, head[MAX_N];
int gap[MAX_N], d[MAX_N];
struct Isap {
int n, s, t;
void init(int n, int s, int t) {
this->n = n, this->s = s, this->t = t;
edgecnt = 0;
memset(head, -1, sizeof head);
}
void addedge(int u, int v, long long cap) {
G[edgecnt] = Edge(v, head[u], cap);
head[u] = edgecnt++;
G[edgecnt] = Edge(u, head[v], 0);
head[v] = edgecnt++;
}
long long dfs(int u, long long tot) {
if (u == t) return tot;
int minh = n - 1;
long long leave = tot;
for (int i = head[u]; ~i && leave; i = G[i].nxt) {
int v = G[i].v;
if (G[i].cap > 0) {
if (d[v] + 1 == d[u]) {
long long c = dfs(v, min(leave, G[i].cap));
G[i].cap -= c;
G[i ^ 1].cap += c;
leave -= c;
if (d[s] >= n)
return tot - leave;
}
minh = min(minh, d[v]);
}
}
if (leave == tot) {
--gap[d[u]];
if (gap[d[u]] == 0) d[s] = n;
d[u] = minh + 1;
++gap[d[u]];
}
return tot - leave;
}
long long maxFlow() {
long long ret = 0;
memset(gap, 0, sizeof gap);
memset(d, 0, sizeof d);
gap[0] = n;
while (d[s] < n) {
ret += dfs(s, INF);
}
return ret;
}
};
int n, m, k;
int mat[MAX_N][MAX_N];
int c[MAX_N][MAX_N];
inline bool rd(int &n){
int x = 0, tmp = 1;
char c = getchar();
while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
if(c == EOF) return false;
if(c == '-') c = getchar(), tmp = -1;
while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
n = x*tmp;
return true;
}
int main() {
int T;
scanf("%d", &T);
int cas = 0;
while (T-- > 0) {
Isap ans;
scanf("%d%d", &n, &m);
k = 9;
ans.init(n + m + 2, 0, n + m + 1);
int s = 0, t = n + m + 1;
long long sum1 = 0, sum2 = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
ans.addedge(i, n + j, k);
}
}
for (int i = 1; i <= n; ++i) {
int rowSum = 0;
rd(rowSum);
sum1 += rowSum;
ans.addedge(0, i, rowSum);
}
for (int i = 1; i <= m; ++i) {
int colSum = 0;
rd(colSum);
sum2 += colSum;
ans.addedge(n + i, t, colSum);
}
int q = ans.maxFlow();
printf("Case #%d: ", ++cas);
if (sum1 != sum2 || q != sum1) puts("So naive!");
else {
int edge = 0;
n = min(n, 200);
m = min(m, 200);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j, edge += 2) {
mat[i][j] = G[edge ^ 1].cap;
}
}
memset(c, false, sizeof c);
bool f = false;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
for (int l = j + 1; l <= m; ++l) {
bool f1 = false, f2 = false;
if (mat[i][j] != k && mat[i][l] != 0) {// column j could add, column l could dec
if (c[l][j]) {
l = m + 1, j = m + 1, i = n + 1;
f = true;
}
f1 = true;
}
if (mat[i][j] != 0 && mat[i][l] != k) {// column l could add, column j could dec
if (c[j][l]) {
l = m + 1, j = m + 1, i = n + 1;
f = true;
}
f2 = true;
}
if (f1) c[j][l] = true;
if (f2) c[l][j] = true;
}
}
}
if (f) puts("So young!");
else {
puts("So simple!");
}
}
}
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.