Bzoj 1532: [POI2005]Kos-Dicing 二分,网络流
1532: [POI2005]Kos-Dicing
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1373 Solved: 444
[Submit][Status][Discuss]
Description
Dicing 是一个两人玩的游戏,这个游戏在Byteotia非常流行. 甚至人们专门成立了这个游戏的一个俱乐部. 俱乐部的人时常在一起玩这个游戏然后评选出玩得最好的人.现在有一个非常不走运的家伙,他想成为那个玩的最好的人,他现在知道了所有比赛的安排,他想知道,在最好的情况下,他最少只需要赢几场就可以赢得冠军,即他想知道比赛以后赢的最多的那个家伙最少会赢多少场.
Input
第一行两个整数n 和 m, 1 <= n <= 10 000, 0 <= m <= 10 000; n 表示一共有多少个参赛者, m 表示有多少场比赛. 选手从1 到 n编号. 接下来m 行每行两个整数表示该场比赛的两个选手,两个选手可能比赛多场.
Output
第一行表示赢得最多的人最少会赢多少场
Sample Input
4 4
1 2
1 3
1 4
1 2
1 2
1 3
1 4
1 2
Sample Output
1
HINT
Source
题解:
二分+网络流。
S向每场比赛连边为1,每场比赛向两个选手连边为1,每个选手向T连二分的上界cap即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 20020 4 #define INF 1e9 5 struct node 6 { 7 int begin,end,value,next; 8 }edge[4*MAXN]; 9 int cnt,Head[MAXN],S,T,dis[MAXN],q[MAXN],a[MAXN],b[MAXN],n,m,cur[MAXN]; 10 void addedge(int bb,int ee,int vv) 11 { 12 edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].value=vv;edge[cnt].next=Head[bb];Head[bb]=cnt; 13 } 14 void addedge1(int bb,int ee,int vv) 15 { 16 addedge(bb,ee,vv);addedge(ee,bb,vv); 17 } 18 int read() 19 { 20 int s=0,fh=1;char ch=getchar(); 21 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 22 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 23 return s*fh; 24 } 25 void Build(int cap) 26 { 27 memset(Head,-1,sizeof(Head));cnt=1; 28 for(int i=1;i<=m;i++){addedge1(S,n+i,1);addedge1(n+i,a[i],1);addedge1(n+i,b[i],1);} 29 for(int i=1;i<=n;i++)addedge1(i,T,cap); 30 } 31 int BFS() 32 { 33 int head,tail,u,v,i; 34 head=0;tail=1;q[tail]=S; 35 memset(dis,-1,sizeof(dis));dis[S]=0; 36 while(head!=tail) 37 { 38 head++;if(head==20010)head=0; 39 u=q[head]; 40 for(i=Head[u];i!=-1;i=edge[i].next) 41 { 42 v=edge[i].end; 43 if(edge[i].value>0&&dis[v]<0) 44 { 45 dis[v]=dis[u]+1; 46 tail++;if(tail==20010)tail=0; 47 q[tail]=v; 48 } 49 } 50 } 51 if(dis[T]<=0)return 0; 52 else return 1; 53 } 54 int DFS(int u,int minflow) 55 { 56 int used=0,ans=0,i,v; 57 if(u==T)return minflow; 58 for(i=Head[u];i!=-1;i=edge[i].next) 59 { 60 v=edge[i].end; 61 if(edge[i].value>0&&dis[v]==dis[u]+1) 62 { 63 ans=minflow-used; 64 ans=DFS(v,min(ans,edge[i].value)); 65 edge[i].value-=ans; 66 edge[i^1].value+=ans; 67 used+=ans; 68 if(used==minflow)return minflow; 69 } 70 } 71 if(used==0)dis[u]=-1; 72 return used; 73 } 74 int Dinic() 75 { 76 int maxflow=0,ans=0,i; 77 while(BFS()){for(i=1;i<=T;i++)cur[i]=Head[i];ans=DFS(S,INF);if(ans==0)break;maxflow+=ans;} 78 return maxflow; 79 } 80 int main() 81 { 82 int i,l,r,mid,k,ans=0; 83 n=read();m=read(); 84 S=n+m+1;T=S+1; 85 //memset(Head,-1,sizeof(Head));cnt=1; 86 for(i=1;i<=m;i++) 87 { 88 //addedge1(S,n+i,1); 89 a[i]=read();b[i]=read(); 90 //addedge1(n+i,a,INF); 91 //addedge1(n+i,b,INF); 92 } 93 //cntcnt=cnt; 94 l=1;r=m; 95 while(l<=r) 96 { 97 mid=(l+r)/2; 98 Build(mid); 99 k=Dinic(); 100 if(k>=m){ans=mid;r=mid-1;} 101 else l=mid+1; 102 } 103 printf("%d",ans); 104 return 0; 105 }