由题目可知若想要一个队伍能够拿到冠军
首先就是先让这个队伍拿到后续比赛所有的分
然后将其他的比赛平均分给 其他队伍 并且他们的分不能大于这个队伍
所以我们只需要将剩余比赛匹配给剩余队伍就行
一开始我还想着去贪心 贪心贪着发现 还是得二分匹配去匹配最优
那这个问题完全可以转换为 二分匹配去匹配最优解 如果全都匹配成功了那么这个队伍就可以成为冠军
匈牙利的复杂度大概是n^3 点的个数大概为 3000 边大概为3000 所以 超时
所以必须使用hk算法 或者 最大流
最大流的话我们只需要将每次比赛当成一个点 源点连向这个比赛 这个比赛连向两个人
两个人连向汇点 即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
using namespace std;
const int N = 30,M = N * 110 * 2;
int n,m,S,T;
int a[N],b[N],gam[N][N],out[N];
int head[3000],to[M],w[M],last[M],cnt;
void add(int a,int b,int c){
to[++cnt] = b;
w[cnt] = c;
last[cnt] = head[a];
head[a] = cnt;
to[++cnt] = a;
w[cnt] = 0;
last[cnt] = head[b];
head[b] = cnt;
}
int d[3000],cur[3000];
bool bfs(){
memset(d,0,sizeof d);
d[S] = 1;
queue<int>q;
q.push(S);
cur[S] = head[S];
while(q.size()){
int p = q.front();
q.pop();
for(int i = head[p]; i != -1; i = last[i]){
int j = to[i];
if(!d[j] && w[i]){
d[j] = d[p] + 1;
cur[j] = head[j];
q.push(j);
if(j == T) return true;
}
}
}
return false;
}
int dfs(int x,int sum){
if(x == T) return sum;
int used = 0;
for(int i = cur[x]; i != -1; i = last[i]){
cur[x] = i;
int j = to[i];
if(d[j] == d[x] + 1 && w[i]){
int dd = dfs(j,min(sum - used,w[i]));
w[i] -= dd;
w[i ^ 1] += dd;
used += dd;
}
}
if(used == 0) d[x] = -1;
return used;
}
int total;
bool dinic(){
int sum = 0;
while(bfs()){
sum += dfs(S,INF);
}
return sum == total;
}
int main(){
cin >> n;
for(int i = 1; i <= n; i++){
scanf("%d%d",&a[i],&b[i]);
}
S = 0,T = 100 * 25 + n + 1;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
scanf("%d",&gam[i][j]);
}
}
int idx = 0;
for(int i = 1; i <= n; i++){
memset(head,-1,sizeof head);
cnt = 1,total = 0;
int maxn = 0,sum = 0;
for(int j = 1; j <= n; j++){
if(i != j) maxn = max(maxn,a[j]);
sum += gam[i][j];
}
if(a[i] + sum < maxn) continue;
int ans = 0;
for(int j = 1; j <= n; j++){
if(i == j) continue;
for(int k = j + 1; k <= n; k++){
if(k == i) continue;
total += gam[j][k];
add(S,++ans,gam[j][k]);
add(ans,100 * 25 + j,INF);
add(ans,100 * 25 + k,INF);
}
add(100 * 25 + j,T,a[i] + sum - a[j]);
}
if(dinic()){
out[++idx] = i;
}
}
for(int i = 1; i <= idx; i++){
cout << out[i] << ' ';
}
return 0;
}