【题意】
有n个队伍进行比赛,每场比赛,恰好有一支队伍取胜、一支队伍败。每个队伍需要打的比赛场数相同,给你每个队伍目前已经赢得场数和输得场数,再给你一个矩阵,第 i 行第 j 列 表示队伍 i 和队伍 j 还需要打的比赛数,问你哪些队伍有可能获得冠军(胜场最多的即为冠军,可以并列)。
Input
The input consists of T test cases. The number of test cases (T) is given in the first line of the input
file.
Each test case consists of three lines: the first line has an integer n(1 ≤ n ≤ 25), that represents the
number of teams in the test case; the second line contains 2n nonnegative integers w1, d1, w2, d2, . . . , wn, dn,
each at most 100, where wi and di are the current numbers of wins and defeats for team i, respectively;
the third line contains n
2 nonnegative integers a1,1, a1,2, . . . , a1,n, a2,1, a2,2, . . . , a2,n, · · · , an,1, an,2, . . . , an,n,
each at most 10, where ai,j is the remaining number of games to be played between teams i and j. For
all i and j, ai,j is equal to aj,i. If i = j, then ai,j = 0. The integers given in a line are delimited by one
or more spaces.
Output
Print exactly one line for each test case. The line should contain all teams that have a possibility of
winning the championship, in an increasing order of team numbers.
Sample Input
3
3
2 0 1 1 0 2
0 2 2 2 0 2 2 2 0
3
4 0 2 2 0 4
0 1 1 1 0 1 1 1 0
4
0 3 3 1 1 3 3 0
0 0 0 2 0 0 1 0 0 1 0 0 2 0 0 0
Sample Output
1 2 3
1 2
2 4
【分析】
枚举判断每个队伍是否可以是冠军。
然后贪心的思想,想让他在接下来的比赛中全部获胜,接下来只用判断其他队伍的比赛是否可以相互制约,使得枚举的是总冠军。
st->(u,v),表示比赛,流量为比场数。
(u,v)->u (u,v)->v 流量为INF
u->ed 流量为tot-w[u] ,tot为枚举的那个的现在计算出的胜利场数,如果他是冠军,那么其他队伍的胜利场数不能超过他。
跑最大流,然后判断st->xxx 是否满流。
这题跟公平分配问题是相似的模型。
把每场比赛看成“任务”,每支队伍看成“处理器”,tot是制约(相当于我们二分的答案)。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 #define Maxn 30 9 #define Mn 1010 10 #define INF 0xfffffff 11 12 struct node 13 { 14 int x,y,f,o,next; 15 }t[Mn*4]; 16 int len,first[Mn]; 17 18 int mymin(int x,int y) {return x<y?x:y;} 19 20 void ins(int x,int y,int f) 21 { 22 if(f<=0) return; 23 t[++len].x=x;t[len].y=y;t[len].f=f; 24 t[len].next=first[x];first[x]=len;t[len].o=len+1; 25 t[++len].x=y;t[len].y=x;t[len].f=0; 26 t[len].next=first[y];first[y]=len;t[len].o=len-1; 27 } 28 29 int w[Maxn],d[Maxn],a[Maxn][Maxn]; 30 int n; 31 32 void init() 33 { 34 scanf("%d",&n); 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%d%d",&w[i],&d[i]); 38 } 39 for(int i=1;i<=n;i++) 40 for(int j=1;j<=n;j++) 41 scanf("%d",&a[i][j]); 42 for(int i=1;i<=n;i++) 43 { 44 a[i][0]=0; 45 for(int j=1;j<=n;j++) a[i][0]+=a[i][j]; 46 } 47 } 48 49 int dis[Mn],st,ed; 50 queue<int > q; 51 bool bfs() 52 { 53 while(!q.empty()) q.pop(); 54 memset(dis,-1,sizeof(dis)); 55 q.push(st);dis[st]=0; 56 while(!q.empty()) 57 { 58 int x=q.front(); 59 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 60 { 61 int y=t[i].y; 62 if(dis[y]==-1) 63 { 64 dis[y]=dis[x]+1; 65 q.push(y); 66 } 67 } 68 q.pop(); 69 } 70 if(dis[ed]==-1) return 0; 71 return 1; 72 } 73 74 int ffind(int x,int flow) 75 { 76 if(x==ed) return flow; 77 int now=0; 78 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 79 { 80 int y=t[i].y; 81 if(dis[y]==dis[x]+1) 82 { 83 int a=ffind(y,mymin(flow-now,t[i].f)); 84 t[i].f-=a; 85 t[t[i].o].f+=a; 86 now+=a; 87 } 88 if(now==flow) break; 89 } 90 if(now==0) dis[x]=-1; 91 return now; 92 } 93 94 int max_flow() 95 { 96 int ans=0; 97 while(bfs()) 98 { 99 ans+=ffind(st,INF); 100 } 101 return ans; 102 } 103 104 int main() 105 { 106 int T; 107 scanf("%d",&T); 108 while(T--) 109 { 110 init(); 111 bool op=0; 112 for(int i=1;i<=n;i++) 113 { 114 int tot=a[i][0]+w[i],cnt,sum=0; 115 len=0; 116 memset(first,0,sizeof(first)); 117 st=n+1,ed=st+1,cnt=ed; 118 bool ok=1; 119 for(int j=1;j<=n;j++) if(j!=i) 120 { 121 ins(j,ed,tot-w[j]); 122 if(tot-w[j]<0) ok=0; 123 } 124 for(int j=1;j<=n;j++) if(j!=i) 125 for(int k=j+1;k<=n;k++) if(k!=i) 126 { 127 sum+=a[j][k]; 128 ins(st,++cnt,a[j][k]),ins(cnt,j,INF),ins(cnt,k,INF); 129 } 130 int x=max_flow(); 131 if(x!=sum) ok=0; 132 if(ok) 133 { 134 if(op) printf(" "); 135 op=1; 136 printf("%d",i); 137 } 138 } 139 // if(T) 140 printf("\n"); 141 } 142 return 0; 143 }
输出文件末不输出空行是WA,行末有空格是PE,也是。。
2016-11-04 07:47:58