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

    uoj
    luogu
    bzoj

    sol

    你可以列一个表格。

    一个框子里放球的数量 0 1 2 3
    对“半空框子”数量的贡献 1 1 0 0

    把一个框子拆三个点。两两之间连边。
    会发现,如果这三个点里一个都没有被球匹配掉,那么这三个点的最大匹配数是(1);如果任意一个点被一个球匹配掉了,那么剩下两个点一定可以匹配,所以最大匹配数还是(1);有两个点或者是三个点被匹配后最大匹配就是(0)
    所以,按如上方式建图,每个球向它可以放进的框子对应的的三个点都连边。跑出最大匹配后输出(ans-n)就好了。(因为(n)个球是一定可以被匹配的)

    update:yyb跟我说他在WA了若干次后发现了一件有趣的事情。
    因为只有增广成功时才会修改匹配,所以如果先匹配框子再匹配球的话,不能保证球一定出现在最大匹配中,所以在输出方案的时候会出问题。
    所以就一定要先匹配球再匹配框子。

    code

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 1005;
    int T,n,m,q,to[N*N],nxt[N*N],head[N],cnt;
    int match[N],vis[N],pre[N],fa[N],tim[N],idx,ans;
    queue<int>Q;
    void link(int u,int v)
    {
    	to[++cnt]=v;nxt[cnt]=head[u];
    	head[u]=cnt;
    	to[++cnt]=u;nxt[cnt]=head[v];
    	head[v]=cnt;
    }
    int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
    int lca(int x,int y)
    {
    	for (++idx;;swap(x,y))
    		if (x)
    		{
    			x=find(x);
    			if (tim[x]==idx) return x;
    			else tim[x]=idx,x=pre[match[x]];
    		}
    }
    void blossom(int x,int y,int p)
    {
    	while (find(x)!=p)
    	{
    		pre[x]=y;y=match[x];
    		if (vis[y]==2) vis[y]=1,Q.push(y);
    		if (find(x)==x) fa[x]=p;
    		if (find(y)==y) fa[y]=p;
    		x=pre[y];
    	}
    }
    int Aug(int S)
    {
    	for (int i=n+3*m;i;--i)
    		vis[i]=pre[i]=0,fa[i]=i;
    	while (!Q.empty()) Q.pop();
    	Q.push(S);vis[S]=1;
    	while (!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=nxt[e])
    		{
    			int v=to[e];
    			if (find(u)==find(v)||vis[v]==2) continue;
    			if (!vis[v])
    			{
    				vis[v]=2;pre[v]=u;
    				if (!match[v])
    				{
    					for (int x=v,lst;x;x=lst)
    						lst=match[pre[x]],match[x]=pre[x],match[pre[x]]=x;
    					return 1;
    				}
    				vis[match[v]]=1;Q.push(match[v]);
    			}
    			else
    			{
    				int gg=lca(u,v);
    				blossom(u,v,gg);blossom(v,u,gg);
    			}
    		}
    	}
    	return 0;
    }
    int main()
    {
    	T=gi();
    	while (T--)
    	{
    		n=gi();m=gi();q=gi();cnt=idx=ans=0;
    		for (int i=n+3*m;i;--i) head[i]=match[i]=tim[i]=0;
    		for (int i=1;i<=q;++i)
    		{
    			int u=gi(),v=gi();
    			link(u+3*m,v),link(u+3*m,v+m),link(u+3*m,v+2*m);
    		}
    		for (int i=1;i<=m;++i)
    			link(i,i+m),link(i,i+2*m),link(i+m,i+2*m);
    		for (int i=n+3*m;i;--i) if (!match[i]) ans+=Aug(i);
    		printf("%d
    ",ans-n);
    		for (int i=1+3*m;i<=n+3*m;++i) printf("%d ",(match[i]-1)%m+1);
    		puts("");
    	}
    	return 0;
    }
    
  • 相关阅读:
    unsupported jsonb version number 123
    如何在MPlayer上支持RTSP
    TDengine 时序数据库的 ADO.Net Core 提供程序 Maikebing.EntityFrameworkCore.Taos
    如何使用IoTSharp对接ModBus?
    如何从源码启动和编译IoTSharp
    Asp.Net Core 自动适应Windows服务、Linux服务、手动启动时的内容路径的扩展方法
    MQTTnet 的Asp.Net Core 认证事件的扩展
    Asp.Net Core 中利用QuartzHostedService 实现 Quartz 注入依赖 (DI)
    The remote certificate is invalid according to the validation procedure 远程证书验证无效
    settings插拔式源码
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8717308.html
Copyright © 2011-2022 走看看