【刷题】UOJ #171 【WC2016】挑战NPC
小 N 最近在研究 NP 完全问题,小 O 看小 N 研究得热火朝天,便给他出了一道这样的题目:
有 \(n\) 个球,用整数 \(1\) 到 \(n\) 编号。还有 \(m\) 个筐子,用整数 \(1\) 到 \(m\) 编号。
每个筐子最多能装 3 个球。
每个球只能放进特定的筐子中。具体有 \(e\) 个条件,第 \(i\) 个条件用两个整数 \(vi\) 和 \(ui\) 描述,表示编号为 \(vi\) 的球可以放进编号为 \(ui\) 的筐子中。
每个球都必须放进一个筐子中。如果一个筐子内有不超过 \(1\) 个球,那么我们称这样的筐子为半空的。
求半空的筐子最多有多少个,以及在最优方案中,每个球分别放在哪个筐子中。
小 N 看到题目后瞬间没了思路,站在旁边看热闹的小 I 嘿嘿一笑:“水题!”
然后三言两语道出了一个多项式算法。
小 N 瞬间就惊呆了,三秒钟后他回过神来一拍桌子:
“不对!这个问题显然是 NP 完全问题,你算法肯定有错!”
小 I 浅笑:“所以,等我领图灵奖吧!”
小 O 只会出题不会做题,所以找到了你——请你对这个问题进行探究,并写一个程序解决此题。
输入格式
第一行包含 \(1\) 个正整数 \(T\) ,表示有 \(T\) 组数据。
对于每组数据,第一行包含 \(3\) 个正整数 \(n,m,e\) ,表示球的个数,筐子的个数和条件的个数。
接下来 \(e\) 行,每行包含 \(2\) 个整数 \(vi,ui\) ,表示编号为 \(vi\) 的球可以放进编号为 \(ui\) 的筐子。
输出格式
对于每组数据,先输出一行,包含一个整数,表示半空的筐子最多有多少个。
然后再输出一行,包含 \(n\) 个整数 \(p1,p2,…,pn\) ,相邻整数之间用空格隔开,表示一种最优解。其中 \(pi\) 表示编号为 \(i\) 的球放进了编号为 \(pi\) 的筐子。如果有多种最优解,可以输出其中任何一种。
样例一
input
1
4 3 6
1 1
2 1
2 2
3 2
3 3
4 3
output
2
1 2 3 3
样例二
见样例数据下载。
限制与约定
对于所有数据,\(T≤5\) ,\(1≤n≤3m\) 。保证 \(1≤vi≤n,1≤ui≤m\) ,且不会出现重复的条件。
保证至少有一种合法方案,使得每个球都放进了筐子,且每个筐子内球的个数不超过 \(3\) 。
各测试点满足以下约定:
测试点编号 | $m$ | 约定 |
---|---|---|
$1$ | $\leq 10$ | $n \leq 20,e \leq 25$ |
$2$ | ||
$3$ | $\leq 100$ | $e=nm$ |
$4$ | 存在方案使得有 $m$ 个半空的筐子 | |
$5$ | 不存在有半空的筐子的方案 | |
$6$ | ||
$7$ | 无 | |
$8$ | ||
$9$ | ||
$10$ |
时间限制: 1s
空间限制: 256MB
题解
思路极其巧妙
我们把一个框分成三个点,并且把其中两个点连上一条边
那么一个球与一个框相连就变成了这样:
我们对这个图跑一遍带花树
那么如果只有一个球放进一个框中,这个框对应的三个点就只会有一个被匹配;而剩下的两个点因为有边相连,所以一定会相互匹配
也就是说,半空的框分出的三个点中一定在两个点相互匹配
因为题目保证球全部可以放进框中,所以匹配数一定大于等于 \(n\) ,而多出来的就是这些框分出的点自己的匹配
我们只要得出有多少自己的匹配,就知道有多少半空的框,用匹配的结果减去 \(n\) 就是答案了
要使答案最大,那么匹配的结果越大越好,所以就是跑带花树
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define ball(a,b) ((a-1)*3+b+n)
const int MAXN=300+10,MAXM=100+10,inf=0x3f3f3f3f;
int e,n,m,fa[MAXN<<1],beg[MAXN<<1],level[MAXN<<1],to[MAXN*MAXN*8],nex[MAXN*MAXN*8],link[MAXN<<1],pre[MAXN<<1],clk,vis[MAXN<<1];
std::queue<int> q;
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline int found(int x)
{
if(fa[x]!=x)fa[x]=found(fa[x]);
return fa[x];
}
inline void insert(int x,int y)
{
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
to[++e]=x;
nex[e]=beg[y];
beg[y]=e;
}
inline int LCA(int u,int v)
{
for(clk++;;std::swap(u,v))
if(u)
{
u=found(u);
if(level[u]==clk)return u;
level[u]=clk;u=pre[link[u]];
}
}
inline void blossom(int u,int v,int lca)
{
while(found(u)!=lca)
{
pre[u]=v,v=link[u];
if(vis[v]==2)vis[v]=1,q.push(v);
if(found(u)==u)fa[u]=lca;
if(found(v)==v)fa[v]=lca;
u=pre[v];
}
}
inline int bfs(int s)
{
for(register int i=1;i<=n+3*m;++i)fa[i]=i;
memset(pre,0,sizeof(pre));
memset(vis,0,sizeof(vis));
while(!q.empty())q.pop();
vis[s]=1;
q.push(s);
while(!q.empty())
{
int x=q.front();
q.pop();
for(register int i=beg[x];i;i=nex[i])
{
if(found(x)==found(to[i])||vis[to[i]]==2)continue;
if(!vis[to[i]])
{
vis[to[i]]=2;
pre[to[i]]=x;
if(!link[to[i]])
{
for(register int p=to[i],las;p;p=las)las=link[pre[p]],link[p]=pre[p],link[pre[p]]=p;
return 1;
}
vis[link[to[i]]]=1;q.push(link[to[i]]);
}
else
{
int lca=LCA(x,to[i]);
blossom(x,to[i],lca);blossom(to[i],x,lca);
}
}
}
return 0;
}
int main()
{
static int T,l,ans;
read(T);
while(T--)
{
e=ans=0;
memset(beg,0,sizeof(beg));
memset(link,0,sizeof(link));
read(n);read(m);read(l);
for(register int i=1;i<=l;++i)
{
int u,v;read(u);read(v);
for(register int k=1;k<=3;++k)insert(u,ball(v,k));
}
for(register int i=1;i<=m;++i)insert(ball(i,1),ball(i,3));
for(register int i=1;i<=n+3*m;++i)
if(!link[i])ans+=bfs(i);
write(ans-n,'\n');
for(register int i=1;i<=n;++i)write((link[i]-n+2)/3,' ');
puts("");
}
return 0;
}
【刷题】UOJ #171 【WC2016】挑战NPC的更多相关文章
- [WC2016]挑战NPC(一般图最大匹配)
[WC2016]挑战NPC(一般图最大匹配) Luogu 题解时间 思路十分有趣. 考虑一个筐只有不多于一个球才有1的贡献代表什么. 很明显等效于有至少两个位置没有被匹配时有1的贡献. 进而可以构造如 ...
- [bzoj4405][wc2016]挑战NPC
来自FallDream的博客,未经允许,请勿转载,谢谢. 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个球,用整数1到n编号.还有m个筐子,用整数1到m编号. ...
- BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配
https://www.lydsy.com/JudgeOnline/problem.php?id=4405 这道题大概就是考场上想不出来,想出来也调不出来的题. 把每个桶拆成三个互相有边的点,每个球向 ...
- [UOJ171][WC2016]挑战NPC
uoj luogu bzoj sol 你可以列一个表格. 一个框子里放球的数量 0 1 2 3 对"半空框子"数量的贡献 1 1 0 0 把一个框子拆三个点.两两之间连边. 会发现 ...
- [BZOJ]4405: [wc2016]挑战NPC(带花树)
带花树模板 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...
- [WC2016]挑战NPC
Sol 这做法我是想不到\(TAT\) 每个筐子拆成三个相互连边 球向三个筐子连边 然后跑一般图最大匹配 这三个筐子间最多有一个匹配 那么显然每个球一定会放在一个筐子里,一定有一个匹配 如果筐子间有匹 ...
- bzoj 4405: [wc2016]挑战NPC【带花树】
把每个筐子拆成3个,分别表示放0/1/2个,然后把这三个点两两连起来,每一个可以放在筐里的球都想这三个点连边. 这样可以发现,放0个球的时候,匹配数为1,放1个球的时候,匹配数为1,放2个球的时候,匹 ...
- 刷题[极客大挑战 2019]HardSQL
解题思路 打开是一个登陆框,考点sql注入了,先正常尝试一波 发现居然是get类型 输入and发现有waf过滤,那fuzz一波看看过滤了什么 fuzz union被过滤,并且绕过union的几种方法同 ...
- 「WC2016」挑战NPC
「WC2016」挑战NPC 解题思路 这个题建图非常厉害,带花树什么的只会口胡根本写不动,所以我写了机房某大佬教我的乱搞. 考虑把一个筐 \(x\) 拆成 \(x1,x2,x3\) 三个点,且这三个点 ...
- 【BZOJ4405】【WC2016】挑战NPC(带花树)
[BZOJ4405][WC2016]挑战NPC(带花树) 题面 BZOJ 洛谷 Uoj Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个 ...
随机推荐
- 【原创】linux命令-Axel命令 - linux多线程下载 - 费元星 - 未来星开发团队
[费元星版权Q:9715234] Axel 是 Linux 下一个不错的HTTP/FTP高速下载工具.支持多线程下载.断点续[费元星版权Q:9715234]传,且可以从多个地址或者从一个地址的多个连接 ...
- 第六章 高级I/O函数
第六章 高级I/O函数 6.1 pipe函数 即管道函数,用于进程间的通信. #include<unistd.h> int pipe(int fd[2]); // fd:filedes / ...
- lintcode433 岛屿的个数
岛屿的个数 给一个01矩阵,求不同的岛屿的个数. 0代表海,1代表岛,如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右为相邻. 您在真实的面试中是否遇到过这个题? Yes 样例 在矩阵: ...
- Hbase restFul API
获取hbase版本 curl -vi -X GET -H "Accept: text/xml" http://10.8.4.46:20550/version/cluster1.2. ...
- MyBatis 注解配置及动态SQL
一.注解配置 目前MyBatis支持注解配置,用注解方式来替代映射文件,但是注解配置还是有点不完善,在开发中使用比较少,大部分的企业还是在用映射文件来进行配置.不完善的地方体现在于当数据表中的字段 ...
- 【模板】DFS
int dx[] = { 0,1,0,-1 }; int dy[] = { 1,0,-1,0 }; void dfs()//参数用来表示状态 { if (到达终点状态) { ...//根据题意来添加 ...
- maven项目中没有resource文件夹的问题
之前使用eclipse创建maven项目,文件夹都是建好的,这几次创建,都没有resource文件夹,需要手动创建resource. 现象描述 在eclipse中,创建maven项目有两种方式: 一种 ...
- Python3 标准库:calendar,time
1.calendar import calendar print(calendar.month(2008,8)) #某个月 print(calendar.calendar(2008)) #某年 pri ...
- java面试整理
IO和NIO的区别 这是一个很常见的问题,如果单纯的只回答IO和NIO的区别,只能算及格.我个人觉得应该从以下几个方面回答: 1).IO简介, 2).TCP的三次握手,因为这也是两者的区别之一, 3) ...
- SpringBoot在IDEA下使用JPA
1依赖 使用IDEA构建基于JPA的项目需要引用JPA.MYSQL依赖 2配置文件修改 2.1连接库 spring.datasource.url=jdbc:mysql://localhost:3306 ...