1. 程式人生 > >BZOJ_1532_[POI2005]Kos-Dicing_二分+網絡流

BZOJ_1532_[POI2005]Kos-Dicing_二分+網絡流

ini CP sca ems 最好的 sin name amp algorithm

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]);
    }*/
}

BZOJ_1532_[POI2005]Kos-Dicing_二分+網絡流