BZOJ1532/POI2005 Dicing

来源:互联网 发布:细说php 编辑:程序博客网 时间:2024/06/18 12:12

直接求似乎不简单,由于题目求”最大值最小问题”,可以转化为二分答案来验证一个解是否成立.假设枚举的答案是x,那么所有人赢得的场次都<=x.而每场比赛最多只有一个人获胜,我们可以根据此信息,构图:
设置源点与每个人建边,每个人与它所参加的每场比赛建边,每场比赛与超级汇点建边并且流量设置为1.根据此图跑一遍最大流,判断是否为m即可.

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int M=10005;const int oo=1e9+5;int head[M<<1],n,m,u[M],v[M],ec=0,tot;int dis[M<<1],flw[M<<1];// dis表示层数 struct node{    int to,cap,nex;}e[M*8];//边数 (n+3*m)*2 int Q[M<<2];inline void rd(int &res){    res=0;char c;    while(c=getchar(),c<48);    do res=(res<<1)+(res<<3)+(c^48);    while(c=getchar(),c>=48);}void ins(int a,int b,int c){    e[ec]=(node){b,c,head[a]};    head[a]=ec++;    e[ec]=(node){a,0,head[b]};    head[b]=ec++;}bool BFS(){    memset(dis,-1,sizeof(dis));    int L=0,R=0,i,j,k;    dis[0]=0;    Q[R++]=0;    while(L<R){        int x=Q[L++];        if(x==tot)return true;        for(i=head[x];~i;i=e[i].nex){            int to=e[i].to,cap=e[i].cap;            if(dis[to]==-1&&cap){                dis[to]=dis[x]+1;                Q[R++]=to;            }        }    }    return false;}int dfs(int x,int flw){    if(x==tot)return flw;    int now=0;    for(int i=head[x];~i;i=e[i].nex){        int to=e[i].to,cap=e[i].cap;        if(dis[to]!=dis[x]+1||!cap)continue;        int f=dfs(to,min(flw,cap));        now+=f;        e[i].cap-=f;        e[i^1].cap+=f;        if(now==flw)break;    }    return now;}bool chk(int res){    memset(head,-1,sizeof(head));//初始化    ec=0;    int ans=0,i,j,k,a,b;    for(i=1;i<=n;i++)ins(0,i,res);    for(i=1;i<=m;i++){        ins(u[i],i+n,res);        ins(v[i],i+n,res);        ins(i+n,tot,1);    }//构图    while(BFS()){        do a=dfs(0,oo),ans+=a;        while(a!=0);    }    if(ans==m)return true;    return false;}int main(){    int l,r,i,j,k,ans;    rd(n);rd(m);tot=n+m+1;    for(i=1;i<=m;i++){        rd(v[i]);rd(u[i]);    }    l=(m+n-1)/n;r=m;    while(l<=r){        int mid=l+r>>1;        if(chk(mid)){            ans=mid;r=mid-1;        }else l=mid+1;    }    printf("%d\n",ans);    return 0;}
0 0