题目链接: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. unzip 命令巧用举例

    1.把文件解压到当前目录下 unzip master.zip 2.如果要把文件解压到指定的目录下,需要用到-d参数. unzip -d /tmp master.zip 3.解压的时候,有时候不想覆盖已 ...

  2. 浏览器 <html>相关

    若页面需默认用极速核,增加标签:<meta name="renderer" content="webkit">  https://blog.csdn ...

  3. RESTful API 学习【第1篇】

    一. 什么是RESTful REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移” REST从资源的角 ...

  4. 51nod1049 最大子段和【动态规划】

    N个整数组成的序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+a[i+1]+-+a[j]的连续子段和的最大值.当所给的整数均为负数时和为0. 例如:-2,11,-4,13,-5,- ...

  5. 【JAVA】AES加密

    import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; imp ...

  6. collections、random、hashlib、configparser、logging模块

    collections模块 在内置数据类型(dict.list.set.tuple)的基础上,collections模块还提供了几个额外的数据类型:Counter.deque.defaultdict. ...

  7. Keil MDK下如何设置非零初始化变量(复位后变量值不丢失)

    一些工控产品,当系统复位后(非上电复位),可能要求保持住复位前RAM中的数据,用来快速恢复现场,或者不至于因瞬间复位而重启现场设备.而keil mdk在默认情况下,任何形式的复位都会将RAM区的非初始 ...

  8. PAT 1104 Sum of Number Segments

    Given a sequence of positive numbers, a segment is defined to be a consecutive subsequence. For exam ...

  9. 清北学堂模拟赛d1t6 或和异或(xor)

    题目描述 LYK最近在研究位运算,它研究的主要有两个:or和xor.(C语言中对于|和^) 为了更好的了解这两个运算符,LYK找来了一个2^n长度的数组.它第一次先对所有相邻两个数执行or操作,得到一 ...

  10. [bzoj1704][Usaco2007 Mar]Face The Right Way 自动转身机_贪心

    Face The Right Way 自动转身机 bzoj-1704 Usaco-2007 Mar 题目大意:不想描述题意系列++... ...题目链接 注释:略. 想法:我们直接枚举k,然后从左往右 ...