题目链接: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)的更多相关文章

  1. 2015 多校赛 第五场 1006 (hdu 5348)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题目大意:给出一幅无向图,问是否存在一种方案,使得给每条边赋予方向后,每个点的入度与出度之差小于 ...

  2. 2015 多校赛 第四场 1010 (hdu 5336)

    Problem Description XYZ is playing an interesting game called "drops". It is played on a r ...

  3. 2015 多校赛 第七场 1011 (hdu 5379)

    题意:给定一棵树,树上有 n 个节点.问有多少种方案,使得在每个节点上依次放置数 1~n 后,每个节点的儿子节点上的数连续(比如 1 为根,有1-2,1-3,1-4,则令2,3,4上的数连续),每个子 ...

  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) ...

  5. 2015 多校赛 第三场 1002 (hdu 5317)

    Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more and more i ...

  6. 2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

    题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据 ...

  7. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  8. 【杂题总汇】HDU多校赛第十场 Videos

    [HDU2018多校赛第十场]Videos 最后一场比赛也结束了…… +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和 ...

  9. hdu5379||2015多校联合第7场1011 树形统计

    pid=5379">http://acm.hdu.edu.cn/showproblem.php? pid=5379 Problem Description Little sun is ...

随机推荐

  1. Java类及成员

    Java类及成员 类 类是对一类事物的的描述,是抽象的概念上的定义:类是创建对象的模板: public class TestClass { public static void main(String ...

  2. 零基础到精通Linux,从这篇文章开始

    2018年想做Linux运维的人应该如何学习才能快速精通Linux? Linux入门这么简单,为什么很多人学不会? 想要成为一个合格的运维工程师,到底怎么才能从零开始精通Linux? 作为一个运维小白 ...

  3. php连接数据库的两种方式

    一.mysqli方式连接数据库 $mysql_conf = array( 'host' => 'localhost:3306', 'db' => 'ssql', 'db_user' =&g ...

  4. react typescript 父组件调用子组件

    //父组件import * as React from 'react'import { Input } from 'antd'const Search = Input.Searchimport &qu ...

  5. list.h在用户态下的应用

    一.背景 list.h文件位于linux/include下,内核中链表的操作函数都在其中.它有许多关于链表的操作函数,所以我们可以尝试将list.h拉到用户态中来使用,这样,我们在用户态中若要用到链表 ...

  6. recreate dbcontrol on database 11.2.0.1 using emca

    [oracle@osb ~]$ env | grep ORA ORACLE_SID=ACE ORACLE_BASE=/oracle ORACLE_TERM=xterm ORACLE_HOME=/ora ...

  7. 内存_RAM或ROM_和FLASH存储的真正区别总结

    http://blog.sina.com.cn/s/blog_4b37304d0100fg10.html

  8. hdu 5176 The Experience of Love

    The Experience of Love  Accepts: 11  Submissions: 108  Time Limit: 4000/2000 MS (Java/Others)  Memor ...

  9. Django——4 模板标签 模板的继承与引用

    Django 模板标签 常用标签 模板的继承与引用 模板标签 标签在渲染的过程中提供任意的逻辑 标签语法: 由%}和 {% 来定义的,例如:{%tag%} {%endtag%} 这个定义是刻意模糊的. ...

  10. 创建序列化器,序列化管理器,closureSerializer

    创建序列化器,序列化管理器,closureSerializer //通过反射创建序列化对象 // Create an instance of the class with the given name ...