Description
Zhc很喜欢看某个竞技比赛,比赛的规则是这样的:队伍分成AB两组进行比赛,除了组内比赛,两组之间还会进行一定的比赛,每场比赛赢者得1分,输者不得分,没有平局的情况。 在A组里面Zhc有一支自己非常喜欢的队伍,现在比赛已经进行到一半了,Zhc想知道,他支持的那支队伍有没有可能获得最终的胜利(A组最高分即为胜利,允许多支队伍同时最高分)
Input
第一行输入样例组数T<=110
每组样例第一行输入A组队伍数量n<=400,以及Zhc支持的队伍编号(1-n)K<=n
第二行按编号输入A组各队伍目前的成绩Mark[i]<= 300000
第三行按编号输入A组各队伍剩余比赛总场数Cnt[i]<= 300000
下面有一个N*N的矩阵,其中A[i][j]代表编号i的队伍跟编号j的队伍剩余比赛场数A[i][j]<=100
Output
对每组样例输出”Yes”或者”No”(不用输出引号)代表Zhc支持的队伍能获得最终的胜利,换行处理
Sample Input
1
2 1
5 6
2 2
0 1
1 0
Sample Output
Yes
【题目链接】
题解
匹配问题通常是转化成网络流问题解决的
下面是官方题解
转化为网络流模型:
其中MAX 为第k 队的最高得分,即mark[k]+cnrt[k]。
对于每一个a[i][j],按左半部分建边;
对于每一个点i,向汇点建立一条MAX-mark[i]的边。
从s 向t 跑最大流,如果从s 连向i,j 的边都满流,则第k 个队可以获得胜利。
下面是根据官方题解敲的代码 122ms
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#include<vector>
#define MAX_N 405
#define INF 0x3f3f3f3f
using namespace std;
const int MAXS=10*1024*1024;
char buf[MAXS],*ch;
void read(int &x){
while(*(++ch)<'0');
for(x=0;*ch>='0';++ch) x=x*10+*ch-'0';
}
void read_init(){
ch=buf-1;
fread(buf,1,MAXS,stdin);
}
/**************************** HEAD *****************************/
struct edge{int to,cap,rev,next;};
int pit[MAX_N*MAX_N];
edge dat[MAX_N*MAX_N<<2];
//vector<edge> G[MAX_N*MAX_N];
int lever[MAX_N*MAX_N];
int iter[MAX_N*MAX_N];
int u;
void add_edge(int x,int y,int cap){
dat[u].next=pit[x];
dat[u].to=y;
dat[u].cap=cap;
dat[u].rev=u+1;
pit[x]=u++;
dat[u].next=pit[y];
dat[u].to=x;
dat[u].cap=0;
dat[u].rev=u-1;
pit[y]=u++;
// G[x].push_back((edge){y,cap,G[y].size()});
// G[y].push_back((edge){x,0,G[x].size()-1});
}
void bfs(int s){
memset(lever,-1,sizeof(lever));
lever[s]=0;
queue<int> que;
que.push(s);
while(!que.empty()){
int v=que.front();que.pop();
for(int i=pit[v];i;i=dat[i].next){
edge &e=dat[i];
if(lever[e.to]==-1&&e.cap>0){
lever[e.to]=lever[v]+1;
que.push(e.to);
}
}
}
}
int dfs(int v,int t,int f){
if(v==t) return f;
for(int &i=iter[v];i;i=dat[i].next){
edge &e=dat[i];
if(e.cap>0&&lever[v]<lever[e.to]){
int d=dfs(e.to,t,min(f,e.cap));
if(d>0){
e.cap-=d;
dat[e.rev].cap+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t){
int f,flow=0;
while(true){
bfs(s);
if(lever[t]==-1) return flow;
for(int i=0;i<=t;i++) iter[i]=pit[i];
while(f=dfs(s,t,INF)) flow+=f;
}
}
int Mark[MAX_N];
int Cnt[MAX_N];
int A[MAX_N][MAX_N];
int main()
{
read_init();
int T;read(T);
while(T--){
memset(pit,0,sizeof(pit));u=1;
int n,k;read(n);read(k);
for(int i=1;i<=n;i++) read(Mark[i]);
for(int i=1;i<=n;i++) read(Cnt[i]);
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) read(A[i][j]);
int MAX=Mark[k]+Cnt[k];
for(int i=1;i<=n;i++) A[i][k]=A[k][i]=0;
int s=0,t=n+n*n+1,sum=0;
bool flag=true;
for(int i=1;flag&&i<=n;i++){
if(i==k) continue;
if(MAX-Mark[i]>=0)
add_edge(i,t,MAX-Mark[i]);
else
flag=false;
}
if(!flag){
puts("No");
continue;
}
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(A[i][j]){
add_edge(s,i*n+j,A[i][j]);
add_edge(i*n+j,i,A[i][j]);
add_edge(i*n+j,j,A[i][j]);
sum+=A[i][j];
}
}
}
int flow=max_flow(s,t);
puts(flow==sum?"Yes":"No");
// for(int i=0;i<=t;i++) while(!G[i].empty()) G[i].pop_back();
}
return 0;
}