• 【纪中集训2019.3.23】Deadline


    题意

    描述

    一个二分图((A,B)),每个点额外有一个颜色0或者1;

    匹配时,只能相同颜色的点匹配;

    给出(A)中的颜色,问如何分配(B)种的颜色使得((A,B))的最大匹配最小;

    范围

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

    题解

    • (A)中的点按照标号划分为(v_0和v_1)

    • 将B中的点拆成(u_0)(u_1),(u_0)(u_1)连流量为(1)的边;

    • (S)(v_0)连流量为1的边,(v_1)向​(T)连流量为​(1)的边;

    • (v_0)向原图中相连的(u_0)(inf)边,(u_1)(v_1)(inf)边;

    • 简单说明:

    • 可以转化为一种标号使得最小点覆盖最小;

    • (<S,v_0> , <u_0,u_1> , <v_1,T>) 被割分别代表(v_0,u,v_1)被选入覆盖集;

    • 只需要说明割和合法方案等价:

    • 由于不存在一条从(S)(T)的残量路径,所以要么(u)被割了,要么(u)两边相连的点至少一边被割了;

    • 这和合法方案的条件是等价的;

    • 所以(ans)=最小割;

    • 考试的时候因为当初做网络流的时候没有理解深刻并且有太久没有做了,所以没有做出来;

      #include<bits/stdc++.h>
      #define inf 0x3f3f3f3f
      using namespace std;
      const int N=10010; 
      char gc(){
      	static char*p1,*p2,s[1000000];
      	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      	return(p1==p2)?EOF:*p1++;
      }
      int rd(){
      	int x=0;char c=gc();
      	while(c<'0'||c>'9')c=gc();
      	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
      	return x;
      }
      int n,m,k,o,hd[N],p[N],S,T,d[N],vis[N],cur[N];
      struct Edge{int v,nt,f;}E[N<<1];
      void adde(int u,int v,int f){
      	E[o]=(Edge){v,hd[u],f};hd[u]=o++;
      	E[o]=(Edge){u,hd[v],0};hd[v]=o++;
      }
      bool bfs(){
      	static queue<int>q;
      	for(int i=S;i<=T;++i)d[i]=vis[i]=0;
      	while(!q.empty())q.pop();
      	d[S]=vis[S]=1;q.push(S);
      	while(!q.empty()){
      		int u=q.front();q.pop();
      		for(int i=hd[u];~i;i=E[i].nt)if(E[i].f){
      			int v=E[i].v;
      			if(vis[v])continue;
      			d[v]=d[u]+1;
      			q.push(v);
      			vis[v]=1;
      			if(v==T)return true;
      		}
      	}
      	return false;
      }
      int dfs(int u,int F){
      	if(u==T||!F)return F;
      	int flow=0,f;
      	for(int i=cur[u];~i;i=E[i].nt){
      		int v=E[cur[u]=i].v;
      		if(d[v]==d[u]+1&&(f=dfs(v,min(E[i].f,F)))){
      			flow+=f;F-=f;
      			E[i].f-=f;E[i^1].f+=f;
      			if(!F)break;
      		}
      	}
      	return flow;
      }
      int dinic(){
      	int flow=0;
      	while(bfs()){
      		for(int i=S;i<=T;++i)cur[i]=hd[i];
      		flow+=dfs(S,inf);
      	}
      	return flow;
      }
      int main(){
      	freopen("deadline.in","r",stdin);
      	freopen("deadline.out","w",stdout);
      	memset(hd,-1,sizeof(hd));
      	n=rd();m=rd();k=rd();S=0;T=n+m*2+1;
      	for(int i=1;i<=n;++i)if(p[i]=rd())adde(S,2*m+i,1);else adde(2*m+i,T,1);
      	for(int i=1;i<=m;++i)adde(i*2-1,i*2,1);
      	for(int i=1;i<=k;++i){
      		int u=rd(),v=rd();
      		if(p[u])adde(m*2+u,v*2-1,inf);
      		else adde(v*2,m*2+u,inf);
      	}
      	int ans=dinic();
      	cout<<ans<<endl;
      	return 0;
      }
      
  • 相关阅读:
    Docker 制作定制asp.netcore 的容器
    Windows docker k8s asp.net core
    Ubuntu 18 Kubernetes集群的安装和部署 以及Helm的安装
    ubuntu 18 docker 搭建Prometheus+Grafana
    ubuntn18 docker zabbix+grafana安装和使用
    .net Core MongoDB用法演示
    Ubuntu18 安装搭建Harbor
    ubuntu docker inflxudb(安装 使用 备份 还原 以及python编码) telegraf Grafana
    python selenium爬虫工具
    python selenium IE Firxfor pyinstaller
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10590741.html
Copyright © 2020-2023  润新知