POJ1636

问题重述:

两个监狱中各有m个囚犯,欲对这两个监狱中的囚犯进行等数量的交换。已知某些囚犯不能关押在同一个监狱,求解可以交换人数的最大值k (k < m/2)。

分析:

假设监狱1中的囚犯a与监狱2中的囚犯b不能共存。那么假如对a进行交换,也必须对b进行交换。因此,根据互斥关系建立的连通集两边的成员必须同时进行交换。

求解步骤:

1)  根据已知的互斥关系,采用并查集建立连通集,分别记录每个连通集在两个监狱中的成员数目,记为v1, v2。

2)  采用动态规划算法,用布尔变量dp[i][j]表示监狱1中i个囚犯与监狱2中的j个囚犯进行交换的可行性。则有dp[i][j] = dp[i – v1[k]][j – v2[k]]

3)  满足dp[i][i] = 1, i < m/2的i的最大值即所求的解。

 //Memory: 580K        Time: 63MS
 #include <iostream>
 #include <cstring>
 #include <cstdio>

 using namespace std;

 ;
 int m, r;
 bool g[maxn][maxn];
 int f[maxn];
 int nl[maxn];
 int nr[maxn];
 bool vis[maxn];
 int v1[maxn], v2[maxn];
 int cnt;
 bool dp[maxn][maxn];

 void makeset()
 {
     memset(f, , sizeof(f));
     memset(nl, , sizeof(nl));
     memset(nr, , sizeof(nr));
     ; i <=  * m; i++)
         f[i] = i;
     ; i <= m; i++) {
         nl[i] = ;
         nr[i] = ;
     }
      + m; i <= m * ; i++) {
         nr[i] = ;
         nl[i] = ;
     }
 }

 int find(int a) {
     if (f[a] == a) return a;
     f[a] = find(f[a]);
     return f[a];
 }

 void uni(int a, int b) {
     int sa = find(a);
     int sb = find(b);
     if (sa != sb) {
         f[sa] = sb;
         nl[sb] += nl[sa];
         nr[sb] += nr[sa];
     }
 }

 void init()
 {
     makeset();
     ; i <= m; i++) {
         ; j <= m * ; j++) if (g[i][j]) {
             uni(i, j);
         }
     }
     cnt = ;
     ; i <= m * ; i++) {
         int s = find(i);
         if (s == i) {
             v1[cnt] = nl[s];
             v2[cnt++] = nr[s];
         }
     }
 }

 int main()
 {
     int cas;
     cin >> cas;
     while (cas--) {
         memset(g, , sizeof(g));
         scanf("%d%d", &m, &r);
         int a, b;
         ; i < r; i++) {
             scanf("%d%d", &a, &b);
             g[a][b + m] = ;
         }
         init();

         memset(dp, , sizeof(dp));
         dp[][] = ;
         ; i < cnt; i++) {
             ; j >= ; j--)  ////此处必须进行倒序循环:每次循环的dp都由上一轮循环后序号较小的dp确定,倒序循环避免提前更新序号较小的dp
                 ; k >= ; k--) {  //同上
                      && k + v2[i] <= m/)
                         dp[j + v1[i]][k + v2[i]] = ;
                 }
         }

         ; i >= ; i--) {
             if (dp[i][i]) {
                 cout << i <<endl;
                 break;
             }
         }
     }
     ;
 }

POJ1636 动态规划+并查集的更多相关文章

  1. POJ1417 True Liars 并查集 动态规划 (种类并查集)

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - POJ1417 题意概括 有一群人,p1个好人,p2个坏人. 他们说了n句话.(p1+p2<=600,n ...

  2. 【2019.10.7 CCF-CSP-2019模拟赛 T3】未知的数组(unknown)(并查集+动态规划)

    预处理 考虑模数\(10\)是合数不好做,所以我们可以用一个常用套路: \(\prod_{i=l}^ra_i\equiv x(mod\ 10)\)的方案数等于\(\prod_{i=l}^ra_i\eq ...

  3. [POJ2054]Color a Tree (并查集+贪心)

    POJ终于修好啦 题意 和UVA1205是同一题,在洛谷上是紫题 有一棵树,需要给其所有节点染色,每个点染色所需的时间是一样的都是11.给每个点染色,还有一个开销“当前时间×ci×ci”,cici是每 ...

  4. POJ-1456 Supermarket(贪心,并查集优化)

    Supermarket Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10725 Accepted: 4688 Descript ...

  5. POJ 1417 - True Liars - [带权并查集+DP]

    题目链接:http://poj.org/problem?id=1417 Time Limit: 1000MS Memory Limit: 10000K Description After having ...

  6. POJ1417 True Liars —— 并查集 + DP

    题目链接:http://poj.org/problem?id=1417 True Liars Time Limit: 1000MS   Memory Limit: 10000K Total Submi ...

  7. leetcode 76 dp& 强连通分量&并查集经典操作

    800. Similar RGB Color class Solution { int getn(int k){ return (k+8)/17; } string strd(int k){ char ...

  8. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  9. 关押罪犯 and 食物链(并查集)

    题目描述 S 城现有两座监狱,一共关押着N 名罪犯,编号分别为1~N.他们之间的关系自然也极不和谐.很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突.我们用"怨气值"( ...

随机推荐

  1. Flask学习记录之Flask-Mail

    Flask-Mail可以连接到配置中的SMTP服务器,进行邮件发送,如果没有进行SMTP服务器的配置,将会默认连接到localhost上的 一.配置及初始化 (1)flask应用配置 #配置选项 MA ...

  2. [Flask Security]当不能通过认证的时候制定跳转

    Flask Security这个插件能对用户权限进行很好的控制. 通过三个model实现: User,存放用户数据 Role,存放角色数据 User_Role.存放用户角色信息 user_datast ...

  3. Spring学习笔记--依赖注入

    依赖注入和控制反转:http://baitai.iteye.com/blog/792980出自李刚<轻量级 Java EE 企业应用实战> Java应用是一种典型的依赖型应用,它就是由一些 ...

  4. Java Tips: 使用Pattern.split替代String.split

    String.split方法很常用,用于切割字符串,split传入的参数是正则表达式,它的内部是每次都comiple正则表达式,再调用Pattern.split方法: public String[] ...

  5. 使用laravel的任务调度(定时执行任务)

    laravel中有一个很强大上的功能,只需要在服务器上添加一个cron条目,就可以定时执行所有的laravel任务. 现在有如下数据表: 我想让cron表中的cron字段的值每分钟增加1,那么我需要如 ...

  6. 如何在项目中使用gtest1.6

    问题 gtest1.6版本的README里说该版本不支持make install,其意思就是说你没法通过make命令把gtest安装到/usr/local/lib之类的目录,所以你也没办法通过下面的命 ...

  7. android开发3:四大基本组件的介绍与生命周期

    android开发3:四大基本组件的介绍与生命周期 Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver ...

  8. bat命令大全

    一.简单批处理内部命令简介 1.Echo 命令 打开回显或关闭请求回显功能,或显示消息.如果没有任何参数,echo 命令将显示当前回显设置.   语法 echo [{on│off}] [message ...

  9. JS实现 鼠标放上去 图片自动放大的效果

    前段时间做项目,要实现,一张图片,鼠标放上去图片自动变大的效果,虽然难度不大,但当时也想了一段时间,当时没时间记录一下,现在有时间了,写篇博客把代码给记录一下: 效果如下: 代码如下: <!DO ...

  10. FreeBsdb FAMP Lamp环境

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA1IAAAHlCAIAAABwFFq0AAAgAElEQVR4nO3d23WruhYA0JTmciiGTm