[WC2016]挑战NPC
来源:互联网 发布:网络热敏打印机 编辑:程序博客网 时间:2024/04/26 14:45
前言
这是WC2016的第一题,在场上迅速能发现60分可做。要分成四个部分。最后由于没发现最多只能放三个球就0分了。还有这题不是NPC问题出题人傻逼
题目大意
给定你e个关系第i个关系表明编号为ai的球可以放到编号为bi的筐子里。每个筐子最多放三个球。请你安排方案,让每个球放进一个筐子里,且所装球数不超过1的箱子数最多。
球的个数n<=3*m,筐子的个数m<=100。
巧妙建模
我们将一个筐子拆为三个点,并让它们连边成为三元环。对于每个球建一个点,然后该点对可以放的筐子的点都连上一条边。现在,只要做一般图最大匹配,答案减去n就是答案。
为什么?
假如一个三元环只有不超过一个匹配点,那么显然就会出现一条匹配边,否则就没有匹配边。因此最大匹配减去球数就是所装球数不超过1的箱子的最大值。
至于一般图最大匹配,要使用带花树算法,UOJ有一道模板题。
参考程序
#include<cstdio>#include<algorithm>#include<deque>#include<iostream>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=1000+10,maxm=100000+10;deque<int> dl;int h[maxn],go[maxm*2],next[maxm*2],fa[maxn],f[maxn],type[maxn],match[maxn],vis[maxn];int i,j,k,l,t,n,m,e,tot,ans,cnt,ca,wdc;void add(int x,int y){ go[++tot]=y; next[tot]=h[x]; h[x]=tot;}void link(int x,int y){ add(x,y);add(y,x);}int getf(int x){ return f[x]?f[x]=getf(f[x]):x;}int lca(int x,int y){ ++cnt; while (x||y){ if (x){ x=getf(x); if (vis[x]==cnt) return x; vis[x]=cnt; x=fa[match[x]]; } swap(x,y); }}void change(int u,int y){ int v,p; while (u!=y){ v=match[u],p=fa[v]; if (getf(p)!=y) fa[p]=v; if (type[v]==2){ type[v]=1; dl.push_back(v); } if (!f[u]) f[u]=y; if (!f[v]) f[v]=y; u=p; }}int dfs(int x){ int i,u,v,p; fo(i,1,wdc) type[i]=f[i]=fa[i]=0; type[x]=1; dl.push_back(x); while (!dl.empty()){ u=dl.front(); dl.pop_front(); t=h[u]; while (t){ v=go[t]; t=next[t]; if (type[v]==2||match[v]==u||getf(u)==getf(v)) continue; if (type[v]==1){ p=lca(u,v); if (getf(u)!=p) fa[u]=v; if (getf(v)!=p) fa[v]=u; change(u,p); change(v,p); } else{ if (!match[v]){ while (u){ j=fa[match[u]];k=match[u]; match[u]=v;match[v]=u; v=k;u=j; } while (!dl.empty()) dl.pop_front(); return 1; } else{ fa[v]=u; type[v]=2; type[match[v]]=1; dl.push_back(match[v]); } } } } return 0;}int main(){ scanf("%d",&ca); while (ca--){ tot=0; cnt=0; scanf("%d%d%d",&n,&m,&e); wdc=3*m+n; fill(vis+1,vis+wdc+1,0); fill(h+1,h+wdc+1,0); fill(match+1,match+wdc+1,0); ans=0; fo(i,1,m){ link(3*i-3+1,3*i-3+2); link(3*i-3+2,3*i-3+3); link(3*i-3+3,3*i-3+1); } fo(i,1,e){ scanf("%d%d",&j,&k); link(3*m+j,3*k-3+1); link(3*m+j,3*k-3+2); link(3*m+j,3*k-3+3); } fd(i,wdc,1) if (!match[i]) ans+=dfs(i); printf("%d\n",ans-n); fo(i,1,n) printf("%d ",(match[3*m+i]-1)/3+1); printf("\n"); }}
注意
由于我们需要输出方案
所以要先从代表球的点搞不然只能答案正确方案错误!!!
1 0
- WC2016 挑战NPC
- [WC2016]挑战NPC
- bzoj4405: [wc2016]挑战NPC
- BZOJ4405: [wc2016]挑战NPC
- UOJ 171 [WC2016]挑战NPC
- bzoj4405 [WC2016] 挑战NPC 带花树
- 【UOj】#171. 【WC2016】挑战NPC
- 【BZOJ】4405: [wc2016]挑战NPC
- 【UOJ#171】【WC2016】挑战NPC【带花树】
- WC2016 挑战NPC 一般图匹配
- WC2016 挑战NPC -一般图匹配
- 带花树算法浅谈&&bzoj4405: [wc2016]挑战NPC
- WC2016 NPC
- UOJ171. 挑战NPC【WC2016】【带花树】【一般图匹配】
- uoj171 bzoj 4405: [wc2016]挑战NPC 一般图最大匹配
- [UOJ171][WC2016] 挑战NPC 一般图最大匹配
- BZOJ4405: [wc2016]挑战NPC 一般图最大匹配
- 挑战NPC
- Leetcode 316
- javascript异步过程
- 环状序列(Circular Sequence, ACM/ICPC Seoul 2004, UVa1584)
- [土狗之路]coursera上C语言进阶习题 括号匹配
- Hdu2066(一个人的旅行)
- [WC2016]挑战NPC
- p275第十章函数和指针
- python教程1安装环境
- 《machine learning with spark》学习笔记--推荐模型
- Python 安装包,简易方法
- % 运算符 2
- java集合基础
- Struts2的工作原理
- Reactor构架模式