• 【BZOJ4443】【SCOI2015】—小凸玩矩阵(二分+最大匹配)


    传送门

    简单题

    考虑二分转化成判断性问题

    既然总共能选且只能选nn
    那也就变成了能否选出nk+1n-k+1个比他小的元素
    dinicdinic跑最大匹配就完了

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=300;
    const int M=100005;
    const int inf=1e9;
    int str,des,adj[M],nxt[M<<1],to[M<<1],cap[M<<1],lev[M],tp[M],cnt=1,n,m,k,num;
    inline void addedge(int u,int v,int w){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,cap[cnt]=w;
    	nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,cap[cnt]=0;
    }
    struct node{
    	int x,y,val;
    	friend inline bool operator <(const node &a,const node &b){
    		return a.val<b.val;
    	}
    }p[M];
    inline bool bfs(){
    	memset(lev,-1,sizeof(lev));
    	queue<int> q;
    	lev[str]=0,q.push(str);
    	while(!q.empty()){
    		int u=q.front();q.pop();
    		for(int e=adj[u];e;e=nxt[e]){
    			int v=to[e];
    			if(cap[e]>0&&lev[v]==-1){
    				lev[v]=lev[u]+1,q.push(v);
    				if(v==des)return true;
    			}
    		}
    	}
    	return false;
    }
    int dfs(int u,int flow){
    	if(u==des)return flow;
    	int res=0;
    	for(int &e=tp[u];e;e=nxt[e]){
    		int v=to[e];
    		if(cap[e]>0&&lev[v]==lev[u]+1){
    			int now=dfs(v,min(cap[e],flow-res));
    			res+=now,cap[e]-=now,cap[e^1]+=now;
    			if(flow==res)break;
    		}
    	}
    	return res;
    }
    inline int dinic(){
    	int res=0;
    	while(bfs()){
    		memcpy(tp,adj,sizeof(adj));
    		res+=dfs(str,inf);
    	}
    	return res;
    }
    inline int check(int k){
    	memset(adj,0,sizeof(adj)),cnt=1;
    	for(int i=1;i<=n;i++)addedge(str,i,1);
    	for(int i=1;i<=m;i++)addedge(n+i,des,1);
    	for(int i=1;i<=num&&p[i].val<=k;i++){
    		addedge(p[i].y,p[i].x+n,1);
    	}
    	return dinic();
    }
    int main(){
    	n=read(),m=read(),k=read();
    	str=n+m+1,des=str+1;
    	for(int i=1;i<=n;i++){
    		for(int j=1;j<=m;j++)
    			p[++num].val=read(),p[num].y=i,p[num].x=j;
    	}
    	sort(p+1,p+num+1);
    	int l=0,r=inf,ans=0,z;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if((z=check(mid))>=n-k+1)r=mid-1,ans=mid;
    		else l=mid+1;
    	}
    	cout<<ans;
    }
    
  • 相关阅读:
    HDU 3152 Obstacle Course(BFS+优先队列 重载)
    芸芸毕业生
    shell学习三十四天----printf具体解释
    tomcat启动批处理——catalina.bat
    ZooKeeper启动过程2:FastLeaderElection
    R语言——数据分析的一把利剑
    Oracle blob字段的插入和更新
    [LeetCode] 698. Partition to K Equal Sum Subsets
    小知识!
    小知识!
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145596.html
Copyright © 2020-2023  润新知