挂在了第二问上,思路是先求出第一问的答案 Ansi ,然后看每个人第二问答案 Anti ,先特判掉 Anti=i 的情况,就是他的最高志愿还低于 si ;再判掉不用提前的情况,即 Ansi≤si 。否则先把 i 的边扔进去找一个增广路,然后从前往后扫他之前的人 j ,j<i ,把这个人可以加的边加进去找增广路,如果找不到的话就说明 i 必须处于 j 前面。请问这个思路有问题吗?数组越界检查了一下好像没事
#include <bits/stdc++.h>
int n, m, s[205], tt, C, b[205], a[205][205], Ans[205], Ant[205], M[205];
std::vector<int>A[205][205];
int head[405], S, T, nxt[100005], ver[100005], len[100005], d[405], tot;
inline void adde(int x, int y, int z){
nxt[++tot] = head[x];
head[x] = tot;
ver[tot] = y;
len[tot] = z;
nxt[++tot] = head[y];
head[y] = tot;
ver[tot] = x;
len[tot] = 0;
return ;
}
int pe[405], pv[405], q[405], vis[405];
int bfs(){
memset(vis, 0, sizeof vis);
int l = 1, r = 0;
q[++r] = S;
vis[S] = 1;
while(l <= r){
int x = q[l];
++l;
for(int i = head[x]; i; i = nxt[i]){
if(vis[ver[i]] || !len[i]) continue;
pv[ver[i]] = i;
pe[ver[i]] = x;
vis[ver[i]] = 1;
q[++r] = ver[i];
if(ver[i] == T) return 1;
}
}
return 0;
}
void ek(){
int t = T;
while(t != S){
--len[pv[t]];
++len[pv[t] ^ 1];
t = pe[t];
}
return ;
}
void init(){
tot = 1;
memset(head, 0, sizeof head);
for(int i = 1; i <= n; ++i) adde(S, i, 1);
for(int i = 1; i <= m; ++i) adde(i + n, T, b[i]);
return ;
}
int main(){
//freopen("mentor5.in", "r", stdin);
scanf("%d%d", &tt, &C);
while(tt--){
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; ++i) scanf("%d", &b[i]);
for(int i = 1; i <= n; ++i){
for(int j = 1; j <= m; ++j){
A[i][j].clear();
}
}
S = n + m + 1;
T = n + m + 2;
init();
for(int i = 1; i <= n; ++i){
M[i] = m + 1;
for(int j = 1; j <= m; ++j){
scanf("%d", &a[i][j]);
if(!a[i][j]) continue;
M[i] = std::min(M[i], a[i][j]);
A[i][a[i][j]].push_back(j);
}
}
for(int i = 1; i <= n; ++i) scanf("%d", &s[i]);
Ans[1] = M[1];
init();
if(Ans[1] != m + 1){
for(int i = 0; i < A[1][Ans[1]].size(); ++i){
int v = A[1][Ans[1]][i];
adde(1, n + v, 1);
}
bfs();
ek();
}
for(int i = 2; i <= n; ++i){
Ans[i] = m + 1;
for(int j = 1; j <= m; ++j){
if(!A[i][j].size()) continue;
for(int k = 0; k < A[i][j].size(); ++k){
int v = A[i][j][k];
adde(i, n + v, 1);
}
memset(pe, 0, sizeof pe);
memset(pv, 0, sizeof pv);
if(bfs()){
ek();
Ans[i] = j;
break;
}
}
}
for(int i = 1; i <= n; ++i) printf("%d ", Ans[i]);
printf("\n");
if(Ans[1] > s[1]) Ant[1] = 1;
else Ant[1] = 0;
for(int i = 2; i <= n; ++i){
if(M[i] > s[i]) {
Ant[i] = i;
continue;
}
else Ant[i] = i - 1;
if(Ans[i] <= s[i]){
Ant[i] = 0;
continue;
}
init();
for(int j = 1; j <= s[i]; ++j){
for(int k = 0; k < A[i][j].size(); ++k){
int v = A[i][j][k];
adde(i, v + n, 1);
}
}
memset(pv, 0, sizeof pv);
memset(pe, 0, sizeof pe);
bfs();
ek();
for(int j = 1; j < i; ++j){
if(Ans[j] == m + 1) continue;
for(int k = 1; k <= Ans[j]; ++k){
for(int p = 0; p < A[j][k].size(); ++p){
int v = A[j][k][p];
adde(j, v + n, 1);
}
}
memset(pe, 0, sizeof pe);
memset(pv, 0, sizeof pv);
if(bfs()){
ek();
Ant[i] = i - j - 1;
}
else break;
}
}
for(int i = 1; i <= n; ++i) printf("%d ", Ant[i]);
printf("\n");
}
return 0;
}
//