1532: [POI2005]Kos-Dicing

1532: [POI2005]Kos-Dicing

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 1403   Solved: 456
[ 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] 

HOME Back



查了题解才知道网络流。。。

可是苟蒻根本想不到

二分答案,每个节点到它参加的比赛连一条容量为1的边

比赛到超级汇连一条容量为1的边

超级源到每个点连一条容量为当前答案的边

dicnic检查当前最大流是否等于m即可


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;

const int maxn = 2E4 + 10;
const int INF = ~0U>>1;

struct E{
	int from,to,cap,flow;
}edgs[maxn*10];

int n,m,cnt,dis[maxn],cur[maxn];

vector <int> v[maxn];
queue <int> q;

void Add(int x,int y,int cap)
{
	edgs[2*cnt] = (E){x,y,cap,0}; v[x].push_back(2*cnt);
	edgs[2*cnt^1] = (E){y,x,0,0}; v[y].push_back(2*cnt^1);
	++cnt;
}

void CLEAR(int now)
{
	for (int i = 0; i <= 2*cnt + 1; i++) edgs[i].flow = 0;
	for (int i = 0; i < n; i++) edgs[i*2].cap = now;
}

bool BFS()
{
	memset(dis,0,sizeof(dis));
	dis[0] = 1; q.push(0);
	while (!q.empty()) {
		int k = q.front(); q.pop();
		for (int i = 0; i < v[k].size(); i++) {
			int to = edgs[v[k][i]].to;
			if (dis[to] || edgs[v[k][i]].flow == edgs[v[k][i]].cap) continue;
			dis[to] = dis[k] + 1;
			q.push(to);
		}
	}
	return dis[n+m+1];
}

int Dicnic(int x,int a)
{
	if (x == n + m + 1 || !a) return a; 
	int flow = 0,f;
	for (int &i = cur[x]; i < v[x].size(); i++) {
		E &e = edgs[v[x][i]];
		if (e.flow == e.cap || (dis[x] + 1) != dis[e.to]) continue;
		f = Dicnic(e.to,min(a,e.cap - e.flow));
		if (f) {
			flow += f;
			a -= f;
			e.flow += f;
			edgs[v[x][i]^1].flow -= f;
			if (!a) break;
		}
	}
	return flow;
}

bool Judge(int now)
{
	CLEAR(now);
	int flow = 0;
	while (BFS()) {
		memset(cur,0,sizeof(cur));
		flow += Dicnic(0,INF);
	}
	return flow == m;
}

int main()
{
	#ifdef YZY
		freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> n >> m;
	for (int i = 1; i <= n; i++) Add(0,i,0);
	for (int i = 1; i <= m; i++) {
		int x,y; scanf("%d%d",&x,&y);
		Add(x,i + n,1); Add(y,i + n,1); Add(i + n,n + m + 1,1);
	}
	int L,R;
	L = 0; R = 10000;
	while (R - L > 1) {
		int mid = (L+R) >> 1;
		if (Judge(mid)) R = mid;
		else L = mid;
	}
	if (Judge(L)) cout << L;
	else cout << R;
	return 0;
}


你可能感兴趣的:(1532: [POI2005]Kos-Dicing)