zoukankan      html  css  js  c++  java
  • 【BZOJ5251】【九省联考2018】—劈配(网络流)

    传送门

    据说匈牙利变一下跑的贼快?
    反正我选择dinicdinic
    第一次跑下来bzojbzoj上倒数第二
    嘤嘤嘤

    第一问很好做
    考虑依次枚举每个人,枚举每种志愿
    跑网络流,看有没有流量
    如果有的话显然是有满足方案的
    没有最好把这一种的边给删了,因为反正以后也没有用了

    第二问考虑可以二分
    然后把这个人提到前面去,连边看能不能跑出来

    为了方便写了个结构体存边
    虽然跑得慢但代码还是清真吧

    #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 inf=1e9;
    const int M=10006;
    const int N=205;
    int str,des,n,m;
    int T,c,mx[N],f[N],ans[N],hp[N];
    vector<int> e[N][N];
    struct Graph{
    	int adj[M],nxt[M<<1],to[M<<1],cap[M<<1],tp[M<<1],lev[M<<1],cnt;
    	Graph(int _cnt=1){cnt=_cnt;}
    	inline void init(){
    		memset(adj,0,sizeof(adj)),cnt=1;
    	}
    	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;
    	}
    	inline void deletedge(int u,int v){
    		adj[u]=nxt[adj[u]],cnt--;
    		adj[v]=nxt[adj[v]],cnt--;
    	}
    	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 dinic(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=dinic(v,min(flow-res,cap[e]));
    				res+=now,cap[e]-=now,cap[e^1]+=now;
    				if(flow==res){
    					
    					return res;
    				}
    			}
    		}
    		return res;
    	}
    }G[N];
    inline void solve1(){
    	for(int i=1;i<=n;i++){
    		G[i]=G[i-1];
    		G[i].addedge(str,i,1);
    		for(int j=1;j<=m;j++){
    			for(int p=0;p<e[i][j].size();p++)
    				G[i].addedge(i,e[i][j][p]+n,1);
    			if(G[i].bfs()){
    				memcpy(G[i].tp,G[i].adj,sizeof(G[i].adj));
    				G[i].dinic(str,inf);
    				ans[i]=j;break;
    			}
    			for(int p=0;p<e[i][j].size();p++)
    				G[i].deletedge(i,e[i][j][p]+n);
    		}
    	}
    	for(int i=1;i<=n;i++){
    		if(!ans[i])ans[i]=m+1;
    		cout<<ans[i]<<" ";
    	}puts("");
    }
    inline bool check(int u,int pt){
    	Graph tg=G[pt-1];
    	tg.addedge(str,u,1);
    	for(int i=1;i<=f[u];i++)
    		for(int j=0;j<e[u][i].size();j++)
    			tg.addedge(u,e[u][i][j]+n,1);
    		
    	if(tg.bfs())return 1;
    	else return 0;
    }
    inline void solve2(){
    	for(int i=1;i<=n;i++){
    		if(ans[i]<=f[i])continue;
    		hp[i]=inf;
    		int l=1,r=i-1;
    		while(l<=r){
    			int mid=(l+r)>>1;
    			if(check(i,mid))hp[i]=mid,l=mid+1;
    			else r=mid-1;
    		}
    		if(hp[i]&&hp[i]!=inf)hp[i]=i-hp[i];
    	}
    	for(int i=1;i<=n;i++)cout<<((hp[i]==inf)?(i):(hp[i]))<<" ";
    	puts("");
    }
    inline void clear(){
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			e[i][j].clear();
    	memset(ans,0,sizeof(ans));
    	memset(hp,0,sizeof(hp));
    	G[0].init();
    }
    inline void solve(){
    	clear();
    	n=read(),m=read();
    	str=n+m+1,des=str+1;
    	for(int i=1;i<=m;i++){
    		mx[i]=read();
    		G[0].addedge(i+n,des,mx[i]);
    	}
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++){
    			int p=read();if(p)
    			e[i][p].push_back(j);
    		}
    	for(int i=1;i<=n;i++)f[i]=read();
    	solve1(),solve2();
    }
    int main(){
    	T=read(),c=read();
    	while(T--)solve();
    }
    
  • 相关阅读:
    javase 超市库存系统
    Javase 简单代码练习
    Javase 简单练习
    SQL表连接查询
    SQL多表查询
    SQL表查询
    SQL数据查询2
    SQL数据查询
    SQL增删改
    AutoCompleteTextView的使用
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145646.html
Copyright © 2011-2022 走看看