码迷,mamicode.com
首页 > 其他好文 > 详细

某某天的模拟赛题 deadline(二分图)

时间:2020-07-12 20:44:33      阅读:54      评论:0      收藏:0      [点我收藏+]

标签:return   out   har   范围   min   inline   网络   adl   pac   

某某天的模拟赛题 deadline(二分图)

题意

给出一个两侧分别有 $ n $ 和 $ m $ 个点, $ k $ 条边的二分图,点会被染成黑白两色,只有同色的点之间的边能使用。

其中左侧点已经给定了每个点的颜色,要你决定右侧每个点的颜色,使得最大匹配最小。

$ 1 \le n \le 2000 , 1 \le m \le 2000 , 1 \le k \le 5000 $ 。

题解

看数据范围可以盲猜网络流。

而且性感理解很容易弄出来正确模型:

左侧白点为第一层,右侧点每个点拆成两个且每对点连1的边作为第二层,左侧黑点作为第三层。

原理?

考虑将问题转化一下:

对于左侧一对黑白点均连接同一个右侧点,则将这对黑白点连边

很明显左侧黑白点按照如上规则组成的新图的最小覆盖便是答案。

众所周知最小覆盖等于最大匹配。

为了减少边数,调整成一开始说的模型即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
template<typename TP>inline void read(TP &tar)
{
	TP ret=0,f=1;char ch=getchar();
	while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){ret=ret*10+(ch-‘0‘);ch=getchar();}
	tar=ret*f;
}
template<typename TP,typename... Args>inline void read(TP& t,Args&... args){read(t),read(args...);}
namespace RKK
{
const int N=6011,M=1000011,inf=0x3f3f3f3f;
struct sumireko{int to,ne;int w;}e[M<<1];int he[N],ecnt=1;
void addline(int f,int t,int w)
{
	e[++ecnt].to=t,e[ecnt].w=w;e[ecnt].ne=he[f],he[f]=ecnt;
	e[++ecnt].to=f,e[ecnt].w=0;e[ecnt].ne=he[t],he[t]=ecnt;
}
void dddline(int f,int t,int w)
{
	e[++ecnt].to=t,e[ecnt].w=w;e[ecnt].ne=he[f],he[f]=ecnt;
	e[++ecnt].to=f,e[ecnt].w=w;e[ecnt].ne=he[t],he[t]=ecnt;
}

int sp,ep,ssp,sep;
int dep[N],cur[N];
queue<int> q;
int bfs(int sp,int ep)
{
	memset(dep,0x00,sizeof(dep));
	memcpy(cur,he,sizeof(cur));
	q.push(sp),dep[sp]=1;
	while(!q.empty())
	{
		int x=q.front();q.pop();
		for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)if(e[i].w&&!dep[t])
			q.push(t),dep[t]=dep[x]+1;
	}
	return dep[ep]!=0;
}
int dfs(int x,int ep,int lim)
{
	if(!lim||x==ep) return lim;
	int ret=0,tmp;
	for(int &i=cur[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
	if(dep[t]==dep[x]+1&&(tmp=dfs(t,ep,min(e[i].w,lim))))
	{
		ret+=tmp,lim-=tmp;
		e[i].w-=tmp,e[i^1].w+=tmp;
		if(!lim) break;
	}
	return ret;
}
int dinic(int sp,int ep){int ret=0;while(bfs(sp,ep)) ret+=dfs(sp,ep,inf);return ret;}

int n,m,em,tp[N];

int main()
{
	freopen("deadline.in","r",stdin),freopen("deadline.out","w",stdout);
	read(n,m,em);sp=n+m+m+1,ep=n+m+m+2;
	for(int i=1;i<=n;i++)
	{
		read(tp[i]);
		if(tp[i]==0) addline(sp,i,1);
		else addline(i,ep,1);
	}for(int i=1;i<=m;i++) addline(n+i,n+m+i,1);
	for(int i=1,x,y;i<=em;i++)
	{
		read(x,y);
		if(tp[x]==0) addline(x,n+y,1);
		else addline(n+m+y,x,1);
	}
	printf("%d\n",dinic(sp,ep));
	return 0;
}
}
int main(){return RKK::main();}

某某天的模拟赛题 deadline(二分图)

标签:return   out   har   范围   min   inline   网络   adl   pac   

原文地址:https://www.cnblogs.com/rikurika/p/13289611.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!