您的位置:首页 > 其它

bzoj 1532: [POI2005]Kos-Dicing (二分+最大流)

2017-01-22 16:56 357 查看

1532: [POI2005]Kos-Dicing

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 1577  Solved: 542

[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



[Submit][Status][Discuss]


题解:二分+最大流

二分一个最大的获胜数mid,最大流判断是否可行

s->每场比赛 容量为1

每场比赛->该场比赛的两名选手 容量为1

每位选手->T 容量为1

看最后的是否满流即可。

这道题卡isap,差评。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cmath>
#define N 100003
#define inf 1000000000
using namespace std;
int x
,y
,n,m;
int tot,point
,nxt
,v
,remain
,lst
,num
;
int deep
,cur
;
void add(int x,int y,int z)
{
tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z;
tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
bool bfs(int s,int t)
{
memset(deep,0x7f,sizeof(deep));
for (int i=1;i<=t;i++)
cur[i]=point[i];
deep[1]=0;
queue<int> p;
p.push(1);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=point[now];i!=-1;i=nxt[i])
{
if(deep[v[i]]>inf&&remain[i])
{
deep[v[i]]=deep[now]+1;
p.push(v[i]);
}
}
}
if (deep[t]>inf) return false;
else return true;
}
int dfs(int now,int t,int limit)
{
if (now==t||!limit) return limit;
int flow=0,f;
for (int i=cur[now];i!=-1;i=nxt[i])
{
cur[now]=i;
if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(limit,remain[i]))))
{
flow+=f; limit-=f;
remain[i]-=f; remain[i^1]+=f;
if (!limit) break;
}
}
return flow;
}
int dinic(int s,int t)
{
int ans=0;
while(bfs(s,t))
ans+=dfs(s,t,inf);
return ans;
}
bool check(int mid)
{
tot=-1;
memset(point,-1,sizeof(point));
memset(num,0,sizeof(num));
int s=1; int t=n+m+2;
for (int i=1;i<=m;i++) {
add(s,i+1,1);
add(i+1,x[i]+m+1,1);
add(i+1,y[i]+m+1,1);
}
for (int i=1;i<=n;i++) add(i+m+1,t,mid);
return dinic(s,t)==m;
}
int main()
{
freopen("a.in","r",stdin);
//freopen("game.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]);
int l=1; int r=m; int ans=m;
while (l<=r) {
int mid=(l+r)/2;
if (check(mid)) ans=min(ans,mid),r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: