zoukankan      html  css  js  c++  java
  • 【纪中集训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;
      }
      
  • 相关阅读:
    为什么要把MySQL的binlog格式修改为row
    面试官:你知道大事务会带来什么问题以及如何解决么?
    TCP三次握手、四次挥手、滑动窗口、流量控制
    SpringCloud Gateway拦截器遇到的小坑汇总
    Zipkin客户端链路追踪源码解析
    Hystrix失败处理逻辑解析
    Feign自动装配原理
    SpringCloud服务调用源码解析汇总
    Zipkin架构简介
    C#+Selenium抓取百度搜索结果前100网址
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10590741.html
Copyright © 2011-2022 走看看