Bzoj 1532: [POI2005]Kos-Dicing 二分,网络流

1532: [POI2005]Kos-Dicing

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 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

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 }

 

posted @ 2016-03-24 23:54  微弱的世界  阅读(230)  评论(0编辑  收藏  举报