标签:return out har 范围 min inline 网络 adl pac
给出一个两侧分别有 $ 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();}
标签:return out har 范围 min inline 网络 adl pac
原文地址:https://www.cnblogs.com/rikurika/p/13289611.html