BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流

BZOJ_1532_[POI2005]Kos-Dicing_二分+网络流

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


 

首先二分答案x,转化成判定是否存在一种方案,

使得所有人赢的次数都小于等于x。

然后对每个人和每场比赛建立二分图。

S->人i(x)

人->比赛(1)

比赛->T(1)。

 

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 200050
#define M 800050
#define S (n+m+1)
#define T (n+m+2)
#define inf 0x3f3f3f3f
int head[N],to[M],nxt[M],flow[M],cnt=1,n,m,xx[N],yy[N],ans[N];
int Q[N],l,r,dep[N];
inline void add(int u,int v,int f) {
    to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
    to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
}
bool bfs() {
    memset(dep,0,sizeof(dep));
    dep[S]=1; l=r=0; Q[r++]=S;
    while(l<r) {
        int x=Q[l++],i;
        for(i=head[x];i;i=nxt[i]) {
            if(flow[i]&&!dep[to[i]]) {
                dep[to[i]]=dep[x]+1;
                if(to[i]==T) return 1;
                Q[r++]=to[i];
            }
        }
    }
    return 0;
}
int dfs(int x,int mf) {
    if(x==T) return mf;
    int nf=0,i;
    for(i=head[x];i;i=nxt[i]) {
        if(dep[to[i]]==dep[x]+1&&flow[i]) {
            int tmp=dfs(to[i],min(mf-nf,flow[i]));
            if(!tmp) dep[to[i]]=0;
            nf+=tmp; flow[i]-=tmp; flow[i^1]+=tmp;
            if(nf==mf) break;
        }
    }
    return nf;
}
int dinic() {
    int ans=0;
    while(bfs()) ans+=dfs(S,inf);
    return ans;
}
bool check(int mid) {
    int i;
    memset(head,0,sizeof(head)); cnt=1;
    for(i=1;i<=n;i++) add(S,i,mid);
    for(i=1;i<=m;i++) add(xx[i],i+n,1),add(yy[i],i+n,1);
    for(i=1;i<=m;i++) add(i+n,T,1);
    return dinic()==m;
}
int main() {
    scanf("%d%d",&n,&m);
    int i,j;
    for(i=1;i<=m;i++) scanf("%d%d",&xx[i],&yy[i]);
    int l=1,r=m+1;
    while(l<r) {
        int mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d\n",l);
    /*memset(head,0,sizeof(head)); cnt=1;
    for(i=1;i<=n;i++) add(S,i,l);
    for(i=1;i<=m;i++) add(xx[i],i+n,1),add(yy[i],i+n,1);
    for(i=1;i<=m;i++) add(i+n,T,1);
    int gay=dinic();gay++;
    for(i=1;i<=n;i++) {
        for(j=head[i];j;j=nxt[j]) {
            if(flow[j]==0&&to[j]!=S) ans[to[j]-n]=i;
        }
    }
    for(i=1;i<=m;i++) {
        printf("%d\n",ans[i]==xx[i]);
    }*/
}

 

posted @ 2018-06-15 13:02  fcwww  阅读(140)  评论(0编辑  收藏  举报