BZOJ 2502 上下界网络流

        首先推荐一篇文章http://wenku.baidu.com/link?url=eFIg-AoMXJLIN3iYZzAHmS61E1_eguZurgyYk6HqhZ8fJQLWoR885UIx8q3ADiQiRU62v8KxDhUys4ibYhEn8zID17Otr3hbtQ4GiU8ro6y

        然后就是裸的最小流

        话说网上很多神奇构图都什么心态,二分+Dinic大法好!

#include 
#include 
#include 
#include 

using namespace std;

const int MAXN = 1001;
const int INF = 10000001;

struct Edge
{
	int from,to,cap,flow;
};

int n,S,T,SS,ST;
int dist[MAXN],a[MAXN],cur[MAXN];
bool vis[MAXN];
vector  Edges;
vector  G[MAXN];

void AddEdge(int from,int to,int cap)
{
	Edges.push_back((Edge){from,to,cap,0});
	Edges.push_back((Edge){to,from,0,0});
	int m = Edges.size();
	G[from].push_back(m-2);
	G[to].push_back(m-1);
}

void clear(int mid)
{
	for (int i=0;i Q;Q.push(s);
	dist[s] = 1;
	while (!Q.empty())
	{
		int u = Q.front();Q.pop();
		for (int i=0;i e.flow && dist[e.to] == dist[u]+1)
		{
			int f = dfs(e.to,min(a,e.cap-e.flow),t);
			if (f <= 0) continue;
			e.flow += f;
			Edges[G[u][i]^1].flow -= f;
			flow += f;
			a -= f;
			if (a == 0) break;
		}
	}
	return flow;
}

void Dinic(int s,int t)
{
	while (bfs(s,t))
	{
		memset(cur,0,sizeof(cur));
		dfs(s,INF,t);
	}
}

bool check()
{
	for (int i=0;i e.flow) return false;
	}
	return true;
}

int main()
{
	scanf("%d",&n);
	S = 0, T = n+1;
	SS = n+2, ST = n+3;
	for (int i=1;i<=n;i++)
	{
		int cnt;
		scanf("%d",&cnt);
		for (int j=1;j<=cnt;j++)
		{
			int x;
			scanf("%d",&x);
			AddEdge(i,ST,1);
			AddEdge(SS,x,1);
			AddEdge(i,x,INF);
			vis[x] = true;
		}
		if (cnt == 0) AddEdge(i,T,INF);
	}
	for (int i=1;i<=n;i++) if (!vis[i]) AddEdge(S,i,INF);
	AddEdge(T,S,INF);
	int l = 1, r = 100001;
	while (l+1 != r)
	{
		int mid = (l+r)/2;
		clear(mid);
		Dinic(SS,ST);
		if (check()) r = mid;
		else l = mid;
	}
	printf("%d\n",r);
	return 0;
}


你可能感兴趣的:(BZOJ)