题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=13349
题目大意:有N个球队在同一个赛区,已知他们胜利的场数,还剩下的在赛区内的比赛数和跨赛区的比赛数的和,和在赛区内的比赛对阵矩阵。问,1号球队是否可以不小于其余球队胜利场数的最大值。
感觉大牛的思路很好:先贪心一下,让1号球队赢得所有比赛,其余球队输掉所有跨赛区的比赛。如果此时有球队比1号球队胜利场次多,显然直接输出NO。否则,对于在同一赛区的比赛,我们这样构图。新增源点S,汇点T。对于每个点I,从S向I连一条容量为和1号球队胜利场数之差的弧。对于赛区内的每一个进行K次的对阵(I,J),新增一个点P,从I向P连一条容量为K的弧,从J向P连一条容量为K的弧,从P向T连一条容量为K的弧。这样,去一遍最大流,若所有P指向T的弧都满流,则输出YES,否则输出NO。为什么说所有P指向T的弧都满流就是YES的?假设某条P指向T的弧不满流,则S指向I和S指向J的弧已经满流,但是还比赛还没有打完,不管剩下的比赛谁赢都将比1号球队的胜利场次多。所以若所有P指向T的弧都满流,则输出YES,否则输出NO。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define MAXN 1111 8 #define MAXM 1111111 9 #define inf 1<<30 10 11 struct Edge{ 12 int v,cap,next; 13 }edge[MAXM]; 14 15 int n,vs,vt,NE,NV; 16 int head[MAXN]; 17 18 void Insert(int u,int v,int cap) 19 { 20 edge[NE].v=v; 21 edge[NE].cap=cap; 22 edge[NE].next=head[u]; 23 head[u]=NE++; 24 25 edge[NE].v=u; 26 edge[NE].cap=0; 27 edge[NE].next=head[v]; 28 head[v]=NE++; 29 30 } 31 32 int level[MAXN],gap[MAXN]; 33 void bfs(int vt) 34 { 35 memset(level,-1,sizeof(level)); 36 memset(gap,0,sizeof(gap)); 37 level[vt]=0; 38 gap[0]++; 39 queue<int>que; 40 que.push(vt); 41 while(!que.empty()){ 42 int u=que.front(); 43 que.pop(); 44 for(int i=head[u];i!=-1;i=edge[i].next){ 45 int v=edge[i].v; 46 if(level[v]!=-1)continue; 47 level[v]=level[u]+1; 48 gap[level[v]]++; 49 que.push(v); 50 } 51 } 52 } 53 54 int pre[MAXN],cur[MAXN]; 55 int SAP(int vs,int vt) 56 { 57 bfs(vt); 58 memset(pre,-1,sizeof(pre)); 59 memcpy(cur,head,sizeof(head)); 60 int u=pre[vs]=vs,aug=inf,maxflow=0; 61 gap[0]=NV; 62 while(level[vs]<NV){ 63 bool flag=false; 64 for(int &i=cur[u];i!=-1;i=edge[i].next){ 65 int v=edge[i].v; 66 if(edge[i].cap>0&&level[u]==level[v]+1){ 67 flag=true; 68 aug=min(aug,edge[i].cap); 69 pre[v]=u; 70 u=v; 71 if(v==vt){ 72 maxflow+=aug; 73 for(u=pre[u];v!=vs;v=u,u=pre[u]){ 74 edge[cur[u]].cap-=aug; 75 edge[cur[u]^1].cap+=aug; 76 } 77 aug=inf; 78 } 79 break; 80 } 81 } 82 if(flag)continue; 83 int minlevel=NV; 84 for(int i=head[u];i!=-1;i=edge[i].next){ 85 int v=edge[i].v; 86 if(edge[i].cap>0&&level[v]<minlevel){ 87 minlevel=level[v]; 88 cur[u]=i; 89 } 90 } 91 if(--gap[level[u]]==0)break; 92 level[u]=minlevel+1; 93 gap[level[u]]++; 94 u=pre[u]; 95 } 96 return maxflow; 97 } 98 99 int a[44],b[44]; 100 int map[44][44]; 101 int main() 102 { 103 int sum=0,flag; 104 while(~scanf("%d",&n)){ 105 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 106 for(int i=1;i<=n;i++)scanf("%d",&b[i]); 107 for(int i=1;i<=n;i++) 108 for(int j=1;j<=n;j++) 109 scanf("%d",&map[i][j]); 110 sum=a[1]+b[1]; 111 flag=0; 112 for(int i=2;i<=n;i++){ 113 if(sum<a[i]){ 114 flag=1; 115 break; 116 } 117 } 118 if(flag){ 119 puts("NO"); 120 continue; 121 } 122 vs=0,vt=n*n+n+1,NV=vt+1; 123 NE=0; 124 memset(head,-1,sizeof(head)); 125 for(int i=2;i<=n;i++)Insert(vs,i,sum-a[i]); 126 sum=0; 127 for(int i=2;i<=n;i++){ 128 for(int j=i+1;j<=n;j++){ 129 if(map[i][j]>0){ 130 sum+=map[i][j]; 131 Insert(i,i*n+j,map[i][j]); 132 Insert(j,i*n+j,map[i][j]); 133 Insert(i*n+j,vt,map[i][j]); 134 } 135 } 136 } 137 if(SAP(vs,vt)==sum){ 138 puts("YES"); 139 }else 140 puts("NO"); 141 } 142 return 0; 143 } 144