题解:
假设现在想知道第i支球队能否赢得胜利,首先肯定是让i剩下的比赛都打赢。如果这样赢的次数都比另一支球队j目前赢的次数少,i肯定赢不了,否则就可以知道j最多还能赢几局,也就是j连向T的流量上界。然后把除了i参与之外的所有比赛当作一个节点k,由S向k连一条容量为1的边,再从节点k连向对应的两只队伍即可。跑完最大流如果所有比赛都满流证明i可以取得冠军,否则不能。
双倍经验
code
#include #include #include using namespace std;#define fcl fclose(stdin); fclose(stdout); return 0int n,ans;int w[30],d[30];int A[30][30];struct EDGE{ int to,next,cap,flow;}edge[8000];#define ty (edge[x].to)const int INF=0x3f3f3f3f;int head[2000],tot=1;void Init(){ memset(head,0,sizeof(head)); tot=1;}inline void AddEdge(int a,int b,int c){ edge[++tot].to=b; edge[tot].cap=c; edge[tot].flow=0; edge[tot].next=head[a]; head[a]=tot;}inline void Add(int a,int b,int c){ AddEdge(a,b,c); AddEdge(b,a,0);}int dis[2000],Q[2000],S,T;bool Bfs(){ memset(dis,0x3f,(T+1)<<2); int s=1,t=0; Q[++t]=S; dis[S]=0; while(s<=t){ int u=Q[s++]; for(int x=head[u];x;x=edge[x].next){ if(edge[x].cap>edge[x].flow&&dis[ty]==INF){ dis[ty]=dis[u]+1; Q[++t]=ty; } } } return dis[T]!=INF;}int cur[2000];int Dfs(int u,int a){ if(a==0||u==T) return a; int f2=0,f; for(int& x=cur[u];x;x=edge[x].next){ if(edge[x].cap>edge[x].flow&&dis[ty]==dis[u]+1){ f=Dfs(ty,min(a,edge[x].cap-edge[x].flow)); edge[x].flow+=f; edge[x^1].flow-=f; f2+=f; a-=f; if(a==0) break; } } return f2;}int MaxFlow(){ int res=0; while(Bfs()){ memcpy(cur,head,(T+1)<<2); res+=Dfs(S,INF); } return res;}bool Judge(int a){ int x=w[a]; for(int i=1;i<=n;++i) x+=A[a][i]; for(int i=1;i<=n;++i){ if(i==a) continue; if(x