zoukankan      html  css  js  c++  java
  • luogu P4382 [九省联考2018]劈配

    luogu

    我记得我第一次做这道题的时候屁都不会qwq

    先考虑第一问,暴力是依次枚举每个人,然后从高到低枚举志愿,枚举导师,能选就选.但是可以发现前面的人选的导师可能会导致后面的人本来可以选到这个志愿,但是不能选.这个问题是不是有点眼熟?你可以理解成二分图匹配问题,就是对于每个人,枚举志愿,然后把这个志愿对应的一些导师连边,如果跑匹配能跑出来那么他就是这个志愿,否则撤销刚才的操作

    第二问类似,暴力枚举某个人到了前面的哪一名,然后把前面其他人在第一问中的方案的图先建好,然后把对应志愿(le s_i)的导师加入图,如果有那个人能匹配上那么就可以前进到这一名,还要记得撤销.做的时候可以先枚举后面的人到的名次,然后枚举人,这样前面的人的图可以快速建出来.每个人的答案是当前名次-最大的合法名次

    实现用的是网络流,因为比较方便退流以及撤销边,开个栈栈序撤销.注意及时撤销

    // luogu-judger-enable-o2
    //qwqwq
    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=200+10,M=3e5+10;
    const db eps=1e-4;
    int rd()
    {
    	int x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    int to[M],nt[M],c[M],hd[N<<1],tot=1;
    void add(int x,int y,int z)
    {
    	++tot,to[tot]=y,nt[tot]=hd[x],c[tot]=z,hd[x]=tot;
    	++tot,to[tot]=x,nt[tot]=hd[y],c[tot]=0,hd[y]=tot;
    }
    void wd(){hd[to[tot^1]]=nt[tot],--tot;}
    int stk[M<<3][2],tp;
    void wdflow()
    {
    	while(tp)
    	{
    		int i=stk[tp][0],dt=stk[tp][1];
    		c[i]+=dt,c[i^1]-=dt;
    		--tp;
    	}
    }
    int ps,pt,lv[N<<1];
    queue<int> q;
    bool bfs()
    {
    	for(int i=0;i<=pt;++i) lv[i]=0;
    	lv[ps]=1,q.push(ps);
    	while(!q.empty())
    	{
    		int x=q.front();
    		q.pop();
    		for(int i=hd[x];i;i=nt[i])
    		{
    			int y=to[i];
    			if(c[i]>0&&!lv[y])
    			{
    				lv[y]=lv[x]+1;
    				q.push(y);
    			}
    		}
    	}
    	return lv[pt];
    }
    int dfs(int x,int fw)
    {
    	if(x==pt) return fw;
    	int an=0;
    	for(int i=hd[x];i;i=nt[i])
    	{
    		int y=to[i];
    		if(c[i]>0&&lv[y]==lv[x]+1)
    		{
    			int dt=dfs(y,min(fw,c[i]));
    			stk[++tp][0]=i,stk[tp][1]=dt;
    			c[i]-=dt,c[i^1]+=dt;
    			fw-=dt,an+=dt;
    			if(!fw) break;
    		}
    	}
    	return an;
    }
    int dinic()
    {
    	int an=0,dt;
    	while(bfs())
    		while((dt=dfs(ps,2333333)))
    			an+=dt;
    	return an;
    }
    int n,m,an[N],a2[N],b[N],s[N];
    vector<int> dls[N][N];
    vector<int>::iterator it;
    
    int main()
    {
        int T=rd();
    	rd();
    	while(T--)
    	{
    		n=rd(),m=rd();
    		ps=0,pt=n+m+1;
    		for(int i=0;i<=pt;++i) hd[i]=0;
    		tot=1;
    		for(int i=1;i<=n;++i)
    		{
    			add(ps,i+m,1);
    			for(int j=1;j<=m+1;++j) dls[i][j].clear();
    		}
    		for(int i=1;i<=m;++i) add(i,pt,b[i]=rd());
    		for(int i=1;i<=n;++i)
    			for(int j=1;j<=m;++j)
    				dls[i][rd()].push_back(j);
    		for(int i=1;i<=n;++i)
    		{
    			an[i]=m+1;
    			for(int j=1;j<=m;++j)
    			{
    				if(!dls[i][j].size()) continue;
    				int latt=tot;
    				for(it=dls[i][j].begin();it!=dls[i][j].end();++it)
    					add(i+m,*it,1);
    				tp=0;
    				if(dinic()){an[i]=j;break;}
    				wdflow();
    				while(tot>latt) wd();
    			}
    			printf("%d ",an[i]);
    		}
    		puts("");
    		for(int i=1;i<=n;++i) s[i]=rd();
    		for(int i=0;i<=pt;++i) hd[i]=0;
    		tot=1;
    		for(int i=1;i<=n;++i) add(ps,i+m,1),a2[i]=0;
    		for(int i=1;i<=m;++i) add(i,pt,b[i]);
    		for(int i=1;i<=n;++i)
    		{
    			for(int j=i;j<=n;++j)
    			{
    				if(an[j]<=s[j]){a2[j]=j;continue;}
    				int latt=tot;
    				for(int k=1;k<=s[j];++k)
    				{
    					if(!dls[j][k].size()) continue;
    					for(it=dls[j][k].begin();it!=dls[j][k].end();++it)
    						add(j+m,*it,1);
    				}
    				tp=0;
    				if(dinic()) a2[j]=i;
    				wdflow();
    				while(tot>latt) wd();
    			}
    			for(it=dls[i][an[i]].begin();it!=dls[i][an[i]].end();++it)
    				add(i+m,*it,1);
    			tp=0,dinic();
    		}
    		for(int i=1;i<=n;++i) printf("%d ",i-a2[i]);
    		puts("");
    	}
    	return 0; 
    }
    
  • 相关阅读:
    Scala刮:使用Intellij IDEA写hello world
    翻译器DIY它———算在英文文本中的单词数,字符和行数
    ZOJ3605-Find the Marble(可能性DP)
    我不需要你喜欢我
    thinkphp5的auth权限认证(转自thinkphp官方文档+自己总结)
    程序员中一些老的程序员去哪了
    信息学竞赛学习资料整理
    m_Orchestrate learning system---二十九、什么情况下用数据库做配置字段,什么情况下用配置文件做配置
    按键精灵使用心得
    thinkphp5中的配置如何使用
  • 原文地址:https://www.cnblogs.com/smyjr/p/11479504.html
Copyright © 2011-2022 走看看