算是一道巧妙的最大流问题问题吧
对于每个队伍用最大流求出它是否可以获胜
具体将每两个队伍i,j间的比赛作为点
c
,
c →icap=infi
c →jcap=infi
表示有
a[i][j]
个胜利需要分配给
i
与
再对每个队伍
i
表示他得到的总胜利不能超过当前询问的队伍
now
的胜利次数,
最大流判断是否存在方案.
/****************************************\
* Author : ztx
* Title : [cogs] 329 K- 联赛
* ALG : 网络流
* CMT :
对于每个队伍用最大流求出它是否可以获胜
具体将每两个队伍i,j间的比赛作为点c,
S->c a[i][j]
c->i infi
c->j infi
表示有a[i][j]个胜利需要分配给i与j
再对每个队伍i
i->T W[now]+S[now]-W[i]
表示他得到的总胜利不能超过当前询问的队伍now的胜利次数,
最大流判断是否存在方案.
* Time :
\****************************************/
#include <cstdio>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define Rev(i,r,l) for(i=(r);i>=(l);i--)
#define rev(i,r,l) for(i=(r);i> (l);i--)
typedef long long ll ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
if (CH == '-') NEG = true , CH = getchar() ;
while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
if (NEG) ret = -ret ;
}
template <typename TP>inline void readc(TP& ret) {
while (ret=getchar() , ret<'!') ;
while (CH=getchar() , CH>'!') ;
}
template <typename TP>inline void reads(TP *ret) {
ret[0]=0;while (CH=getchar() , CH<'!') ;
while (ret[++ret[0]]=CH,CH=getchar(),CH>'!') ;
ret[ret[0]+1]=0;
}
#include <cstring>
#define maxn 26LL
int n,sum,w[maxn],a[maxn][maxn],s[maxn];
#define maxN 666LL
#define min(x,y) ((x)<(y)?(x):(y))
#define infi 0x7f7f7f7fLL
int g[maxN][maxN] ;
int N , S , T , h[maxN] , vh[maxN] ;
inline void Edge_init() { memset(g , 0 , sizeof g) ; }
inline void Edge_add(int u,int v,int f) { g[u][v] = f , g[v][u] = 0 ; }
int dfs(int u,int flowu) {
int v,flow,flowv,tmp = h[u]+1 ;
if (u == T) return flowu ;
flow = 0 ;
Rep (v,1,N) if (g[u][v] && h[u]==h[v]+1) {
flowv = dfs(v,min(flowu-flow,g[u][v])) ;
flow += flowv , g[u][v] -= flowv , g[v][u] += flowv ;
if (flow==flowu || h[S]==N) return flow ;
}
Rep (v,1,N) if (g[u][v] && h[v]<tmp)
tmp = h[v] ;
if (--vh[h[u]]==0) h[S] = N ;
else ++vh[h[u]=tmp+1] ;
return flow ;
}
inline void sap(int now) {
int maxflow = 0 , i , j , c = 0 ;
Edge_init() ;
Rep (i,1,n) if (w[i]>w[now]+s[now])
return ;
Rep (i,1,n) if (i!=now)
Rep (j,i+1,n) if (j!=now && a[i][j])
c++ ;
S = n+c+1 , T = N = S+1 ;
c = 0 ;
Rep (i,1,n) if (i!=now)
Edge_add(i,T,w[now]+s[now]-w[i]) ;
Rep (i,1,n) if (i!=now)
Rep (j,i+1,n) if (j!=now && a[i][j]) {
c ++ ;
Edge_add(S,n+c,a[i][j]) ;
Edge_add(n+c,i,infi) ;
Edge_add(n+c,j,infi) ;
}
memset(h,0,sizeof h) ;
memset(vh,0,sizeof vh) ;
vh[S] = N ;
while (h[S] < N) maxflow += dfs(S , infi) ;
if (maxflow == sum-s[now]) printf("%d ",now) ;
return ;
}
int main() {
int i , j ;
#define READ
#ifdef READ
freopen("kleague.in" ,"r",stdin ) ;
freopen("kleague.out","w",stdout) ;
#endif
read(n) ;
Rep (i,1,n)
read(w[i]) , read(j) ;
sum = 0 ;
Rep (i,1,n) {
s[i] = 0 ;
Rep (j,1,n) {
read(a[i][j]) ;
s[i] += a[i][j] ;
sum += a[i][j] ;
}
}
sum >>= 1 ;
Rep (i,1,n) sap(i) ;
puts("") ;
#ifdef READ
fclose(stdin) ; fclose(stdout) ;
#else
getchar() ; getchar() ;
#endif
return 0 ;
}