zoukankan      html  css  js  c++  java
  • [WC2016]挑战NPC

    题目传送门

    分析:
    先使用人类智慧进行构造
    每个筐拆成三个点,相互连边
    每个球向它可以放的筐拆成的三个点连边
    如果一个筐半空,那么拆成的三个点会有两个以上没有和球匹配
    那么它们自身能构成一个匹配
    每个球都能放进去,求一下原图的最大匹配
    答案就是最大匹配-球数
    (又一次被开除人籍

    一般图的最大匹配使用带花树,大致原理是将奇环缩点找增广路
    可以看看网上的讲解

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<map>
    
    #define maxn 1005
    #define maxm 200005
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m,E,N;
    int fir[maxn],nxt[maxm],to[maxm],cnt;
    int tic[maxn],match[maxn],f[maxn],pre[maxn],tp[maxn],tim;
    queue<int>Q;
    
    inline void newnode(int u,int v)
    {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
    inline int find(int x)
    {return f[x]==x?x:f[x]=find(f[x]);}
    inline int LCA(int x,int y)
    {
    	for(++tim;;swap(x,y))if(x)
    	{
    		x=find(x);
    		if(tic[x]==tim)return x;
    		else tic[x]=tim,x=pre[match[x]];
    	}
    }
    inline void shrink(int x,int y,int p)
    {
    	while(find(x)!=p)
    	{
    		pre[x]=y,y=match[x];
    		if(tp[y]==2)tp[y]=1,Q.push(y);
    		if(find(x)==x)f[x]=p;
    		if(find(y)==y)f[y]=p;
    		x=pre[y];
    	}
    }
    
    inline bool aug(int s)
    {
    	for(int i=1;i<=N;i++)f[i]=i;
    	while(!Q.empty())Q.pop();
    	memset(tp,0,sizeof tp),memset(pre,0,sizeof pre);
    	Q.push(s),tp[s]=1;
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=fir[u];i;i=nxt[i])
    		{
    			int v=to[i];
    			if(find(u)==find(v)||tp[v]==2)continue;
    			if(!tp[v])
    			{
    				tp[v]=2,pre[v]=u;
    				if(!match[v])
    				{
    					for(int now=v,lst;now;now=lst)
    					{
    						lst=match[pre[now]];
    						match[pre[now]]=now,match[now]=pre[now];
    					}
    					return 1;
    				}
    				tp[match[v]]=1,Q.push(match[v]);
    			}
    			else
    			{
    				int p=LCA(u,v);
    				shrink(u,v,p),shrink(v,u,p);
    			}
    		}
    	}
    	return 0;
    }
    
    int main()
    {
    	int T=getint();
    	while(T--)
    	{
    		int ans=0;
    		memset(fir,0,sizeof fir),cnt=tim=0;
    		memset(match,0,sizeof match),memset(tic,0,sizeof tic);
    		n=getint(),m=getint(),E=getint();
    		while(E--)
    		{
    			int u=getint(),v=getint();
    			newnode(3*v-2,3*m+u),newnode(3*m+u,3*v-2);
    			newnode(3*v-1,3*m+u),newnode(3*m+u,3*v-1);
    			newnode(3*v-0,3*m+u),newnode(3*m+u,3*v-0);
    		}
    		for(int i=1;i<=m;i++)
    		{
    			newnode(3*i-2,3*i-1),newnode(3*i-1,3*i-2);
    			newnode(3*i-1,3*i-0),newnode(3*i-0,3*i-1);
    			newnode(3*i-0,3*i-2),newnode(3*i-2,3*i-0);
    		}
    		N=3*m+n;
    		for(int i=N;i;i--)ans+=(!match[i]&&aug(i));
    		printf("%d
    ",ans-n);
    		for(int i=1;i<=n;i++)printf("%d ",(match[3*m+i]+2)/3);
    	}
    }
    

  • 相关阅读:
    SecureCRT设置linux终端显示颜色
    OpenCV空洞填充算法
    祝贺自己的软件《万能数据库查询分析器》在非凡软件站和太平洋电脑的下载排行榜分别名列第1和第2
    linux磁盘分区 简要
    linux压缩解压命令
    【可视化】Echarts3坐标系倒映
    【可视化】Echarts3 在世界地图中绘制中国各省份的轮廓
    【Maven】解决linux下安装maven update-alternative --display mvn链接层数过多
    【Ubuntu 16】启动Eclipse Indigo报错 error code1 jdk没有配置好
    oracle体系结构
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13089596.html
Copyright © 2011-2022 走看看