二分答案,比赛与双方选手连边跑最大匹配。。看匹配数是否等于比赛数。
dinic大法好++
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=10233,inf=1002333333; 6 struct zs{ 7 int too,pre,flow; 8 }e[maxn<<3];int tot,last[maxn<<1]; 9 int dl[maxn<<1],dis[maxn<<1],cd[maxn]; 10 int i,j,k,n,m,tt,s,t; 11 12 int ra;char rx; 13 inline int read(){ 14 rx=getchar(),ra=0; 15 while(rx<'0'||rx>'9')rx=getchar(); 16 while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra; 17 } 18 19 inline void insert(int a,int b,int c){ 20 e[++tot].too=b,e[tot].flow=c,e[tot].pre=last[a],last[a]=tot; 21 e[++tot].too=a,e[tot].flow=0,e[tot].pre=last[b],last[b]=tot; 22 } 23 bool bfs(){ 24 int l=0,r=1,now,i; 25 memset(dis,255,(t+1)<<2),dl[1]=s,dis[s]=0; 26 while(l<r&&dis[t]==-1){ 27 now=dl[++l]; 28 for(i=last[now];i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]==-1) 29 dis[e[i].too]=dis[now]+1,dl[++r]=e[i].too; 30 } 31 return dis[t]!=-1; 32 } 33 inline int min(int a,int b){return a<b?a:b;} 34 int dfs(int x,int mx){ 35 if(x==t)return mx; 36 int i,used=0,w; 37 for(i=last[x];i;i=e[i].pre)if(e[i].flow&&dis[e[i].too]==dis[x]+1){ 38 w=dfs(e[i].too,min(e[i].flow,mx-used));if(w){ 39 e[i].flow-=w,e[i^1].flow+=w,used+=w; 40 if(used==mx)return mx; 41 } 42 } 43 dis[x]=-1;return used; 44 } 45 inline bool check(int mid){ 46 register int i;int flow=0; 47 for(i=2;i<=tt;i+=2)e[i].flow=1,e[i^1].flow=0; 48 for(i=tt+1;i<=tot;i+=2)e[i].flow=mid,e[i^1].flow=0; 49 while(bfs())flow+=dfs(s,inf); 50 return flow==m; 51 } 52 int main(){ 53 n=read(),m=read(); 54 s=0,t=n+m+1,tot=1; 55 for(i=1;i<=m;i++) 56 j=read(),k=read(),insert(j,i+n,1),insert(k,i+n,1),cd[j]++,cd[k]++; 57 for(i=1;i<=m;i++)insert(i+n,t,1);tt=tot; 58 for(i=1;i<=n;i++)insert(s,i,0); 59 int l=(m+n-1)/n,r=0,mid; 60 for(i=1;i<=n;i++)if(cd[i]>r)r=cd[i]; 61 while(l<r){ 62 mid=l+r>>1; 63 if(check(mid))r=mid;else l=mid+1; 64 } 65 printf("%d ",l); 66 return 0; 67 }