2015 多校赛 第五场 1010 (hdu 5352)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5352
看题看得心好累。
题目大意:
给出 n 个点,依次执行 m 次操作:输入“1 x”时,表示将与 x 连通的点全部修复;输入“2 x y”,表示在 x 与 y 之间加一条边;输入“3 x y”,表示删除 x 与 y 之间的边。题目确保不会与重边并且操作合法。
题目会给出 k,要求每次修复的的点的数目小于等于k。
问:怎样执行操作1,使得令修复点数最多的同时,令每次执行操作1所修复的点的数目所构成的数列字典序最小。(可以令某次操作无效,或者说令其修复的点数为0)
解题思路:
二分图最大匹配、拆点。
(我反正是看题解才弄明白的。。)
具体实现过程:
首先我们知道二分图最大匹配的用途。在这道题中,左侧点对应于每次操作1,右侧点即所有的点。然后边对应于——每次操作1修复的点 和 与之相连通的点 之间的边。则寻找最大匹配即为寻找在所有操作下所能得到的最大匹配数。
显然操作2与操作3都是为操作1而服务的,直接相关于与操作1所操作的点所连通的点(好累赘。。)。每次执行操作1时,记录与该点相连通的所有点,并给该点与所连通的点建边。这里注意:拆点。将每个点都拆成 k 个点。这样的话,每个操作所得的最大匹配数<=k,即每个操作所修复的点的个数<=k。
图已建好,跑一遍匈牙利算法就可以了(不考虑字典序的情况下)。
要考虑字典序的话,由匈牙利算法的特性易知,则从最后一次操作往前跑匈牙利算法即可。
容易思维卡壳的是,对于每次操作1,与点 x 相连通的点<=k时,全部都选了不就可以了吗等等。
需要注意的是,当下操作得到最大值不一定使得最后的最优值。即局部最优解未必能得到全局最优解,所以才需要用二分图最大匹配算法。
注意对maxn的大小设定。
然后是,这个做法最后做出来是700ms左右,不太理想。据说还可以用最大流和最小费用最大流做。
考虑不换算法的优化的话,首先是用数组模拟邻接表,因为用vector的push_back和clear操作耗时颇大。尤其在初始化调用g[i].clear()的时候,i的边界的设定如果过大的话会导致TLE。具体会快多少不好说。
然后是匈牙利算法换成bfs实现。晚点再写一下看能快多少。
这是上次华师校赛后第二次碰到二分图最大匹配的题,充分体现的该算法理解的不足。模板题和应用题毕竟两回事。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define maxn 555
int n,m,k,T,op,a,b,c,tot,ans,ary[maxn],pic[maxn][maxn];
vector<int>g[maxn*maxn];
int con[maxn],vis[maxn],con_tot[maxn],divp;
void init(){
memset(pic,,sizeof(pic));
memset(ary,,sizeof(ary));
memset(con,,sizeof(con));
divp=ans=tot=;
for(int i=;i<=n*k;i++) g[i].clear();
}
void find_con(int u){
vis[u]=;
con_tot[tot++]=u;
for(int i=;i<=n;i++) if(!vis[i]&&pic[u][i])
find_con(i);
}
int dfs(int u){
for(int i=;i<g[u].size();i++){
int v=g[u][i];
if(!vis[v]){
vis[v]=;
if(!con[v]||dfs(con[v])){
con[v]=u;
return ;
}
}
}
return ;
}
void solve(){
for(int i=divp-;i>=;i--){
for(int j=i*k,lim=(i+)*k;j<lim;j++){
memset(vis,,sizeof(vis));
if(dfs(j)){
ans++;
ary[i]++;
}
}
}
}
int main(){
//freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
init();
for(int i=;i<m;i++){
scanf("%d",&op);
if(op==){
scanf("%d",&a);
tot=;
memset(vis,,sizeof(vis));
find_con(a);
for(int j=;j<tot;j++){
for(int t=k*divp,lim=k*(divp+);t<lim;t++)
g[t].push_back(con_tot[j]);
}
divp++;
}
else if(op==){
scanf("%d%d",&a,&b);
pic[a][b]=pic[b][a]=;
}
else{
scanf("%d",&c);
for(int j=;j<c;j++){
scanf("%d%d",&a,&b);
pic[a][b]=pic[b][a]=;
}
}
}
solve();
printf("%d\n",ans);
for(int i=;i<divp;i++)
printf("%d%c",ary[i],i==divp-?'\n':' ');
}
return ;
}
2015 多校赛 第五场 1010 (hdu 5352)的更多相关文章
- 2015 多校赛 第五场 1006 (hdu 5348)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题目大意:给出一幅无向图,问是否存在一种方案,使得给每条边赋予方向后,每个点的入度与出度之差小于 ...
- 2015 多校赛 第四场 1010 (hdu 5336)
Problem Description XYZ is playing an interesting game called "drops". It is played on a r ...
- 2015 多校赛 第七场 1011 (hdu 5379)
题意:给定一棵树,树上有 n 个节点.问有多少种方案,使得在每个节点上依次放置数 1~n 后,每个节点的儿子节点上的数连续(比如 1 为根,有1-2,1-3,1-4,则令2,3,4上的数连续),每个子 ...
- 2015 多校赛 第四场 1009 (hdu 5335)
Problem Description In an n∗m maze, the right-bottom corner is the exit (position (n,m) is the exit) ...
- 2015 多校赛 第三场 1002 (hdu 5317)
Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more and more i ...
- 2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)
题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据 ...
- NOI.AC NOIP模拟赛 第五场 游记
NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...
- 【杂题总汇】HDU多校赛第十场 Videos
[HDU2018多校赛第十场]Videos 最后一场比赛也结束了…… +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和 ...
- hdu5379||2015多校联合第7场1011 树形统计
pid=5379">http://acm.hdu.edu.cn/showproblem.php? pid=5379 Problem Description Little sun is ...
随机推荐
- VM虚拟机NAT链接外网
1.vi /etc/sysconfig/networkNETWORKING=yesHOSTNAME=localhost.localdomainGATEWAY=192.168.110.2 2.vi /e ...
- 北京Python开发培训怎么选?
北京的地理优势和经济优势基本无需多言,作为全国机会最多的地方,吸引了无数的北漂前赴后继.作为中国互联网中心之一,北京有海量Python岗位正在等待大家淘金. 近几年中,Python一直是市场上最受欢迎 ...
- php连接数据库的两种方式
一.mysqli方式连接数据库 $mysql_conf = array( 'host' => 'localhost:3306', 'db' => 'ssql', 'db_user' =&g ...
- HDU 2451 Simple Addition Expression(找规律,考验智商)
题目 最近比赛的题目好多签到题都是找规律的考验智商的题目啊,,,我怎么越来越笨了,,,, 通过列举,可以发现规律: 从左往右按位扫这个数: 当数的长度大于1时: 当首位大于3时,答案就是4*4*4*… ...
- js 随机数范围
Math.floor(Math.random()*(high-low+1) +low)
- 洛谷——P1896 [SCOI2005]互不侵犯
P1896 [SCOI2005]互不侵犯 状压DP入门题 状压DP一般需要与处理状态是否合法,节省时间 设定状态dp[i][j][k]表示第i行第j个状态选择国王数为k的方案数 $dp[i][j][n ...
- JS练习:显示和隐藏
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 【IntelliJ IDEA】idea上安装Translation插件后,需要AppKey才能生效的解决方案
使用idea安装的翻译插件translation,但是使用的时候并不友好 无奈,如果想使用翻译软件并且更方便的话,可以如下: 可以选择将translation进行卸载 清除缓存并进行重启 然后再启动之 ...
- 【Codeforces 1106D】Lunar New Year and a Wander
[链接] 我是链接,点我呀:) [题意] 让你遍历n个节点,访问过的节点不操作. 如果是没有访问过的点,那就把它加到序列的末尾. 问你形成的最小字典序的序列是多少. [题解] 显然每次找最小的标号 用 ...
- 【codeforces 527A】Playing with Paper
[题目链接]:http://codeforces.com/contest/527/problem/A [题意] 让你每次从一个长方形里面截出一个边长为长方形的较短边的正方形; 然后留下的部分重复上述步 ...