【BZOJ 1532】 [POI2005]Kos

1532: [POI2005]Kos-DicingTime Limit:5 SecMemory Limit:64 MBSubmit:1150Solved:358[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 41 21 31 41 2

Sample Output

1

二分/枚举+网络流

把一场比赛看作资源,分配给获胜者。

我们二分或枚举获胜场数m。

左边一排点表示比赛,右边表示人,s向比赛连流量为1的边,比赛向对战双方连流量为1的边。

每个人向t连流量为m的边,表示限制最多赢m场。

如果满流,说明可行,否则不可行。

我用枚举做的,,因为枚举不用重新建图,直接在原图基础上增加流量即可。

#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <cstdlib>#include <queue>#define inf 0x3f3f3f3f#define M 100000+5using namespace std;int s,t,h[M],cur[M],v[M],d[M],n,m;int tot=1;struct edge{int from,to,cap,flow,ne;}E[200005];void Addedge(int from,int to,int cap){E[++tot]=(edge){from,to,cap,0,h[from]};h[from]=tot;E[++tot]=(edge){to,from,0,0,h[to]};h[to]=tot;}bool bfs(){for (int i=s;i<=t;i++)v[i]=0;v[s]=1;d[s]=0;queue<int> q;q.push(s);while (!q.empty()){int x=q.front();q.pop();for (int i=h[x];i;i=E[i].ne){edge e=E[i];if (!v[e.to]&&e.cap>e.flow){v[e.to]=1;d[e.to]=d[x]+1;q.push(e.to);}}}return v[t];}int dfs(int x,int a){if (x==t||!a) return a;int flow=0;for (int &i=cur[x];i;i=E[i].ne){edge &e=E[i];if (d[e.to]!=d[x]+1) continue;int f=dfs(e.to,min(a,e.cap-e.flow));if (f){flow+=f;a-=f;e.flow+=f;E[i^1].flow-=f;if (!a) break;}}return flow;}int main(){scanf("%d%d",&n,&m);s=0,t=n+m+1;for (int i=1;i<=m;i++){int x,y;scanf("%d%d",&x,&y);Addedge(x,i+n,1);Addedge(y,i+n,1);Addedge(i+n,t,1);}int x=tot;for (int i=1;i<=n;i++)Addedge(s,i,0);int flow=0;for (int i=1;;i++){for (int j=x+1;j<tot;j+=2)E[j].cap+=1;while (bfs()){for (int j=s;j<=t;j++)cur[j]=h[j];flow+=dfs(s,inf);}if (flow==m){cout<<i<<endl;return 0;}}return 0;}

只有不快的斧,没有劈不开的柴。

【BZOJ 1532】 [POI2005]Kos

相关文章:

你感兴趣的文章:

标签云: