zoukankan      html  css  js  c++  java
  • POJ 1636 Prison rearrangement (DP)


    Prison rearrangement
    Time Limit: 3000MSMemory Limit: 10000K
    Total Submissions: 2008Accepted: 906

    Description

    In order to lower the risk of riots and escape attempts, the boards of two nearby prisons of equal prisoner capacity, have decided to rearrange their prisoners among themselves. They want to exchange half of the prisoners of one prison, for half of the prisoners of the other. However, from the archived information of the prisoners' crime history, they know that some pairs of prisoners are dangerous to keep in the same prison, and that is why they are separated today, i.e. for every such pair of prisoners, one prisoners serves time in the first prison, and the other in the second one. The boards agree on the importance of keeping these pairs split between the prisons, which makes their rearrangement task a bit tricky. In fact, they soon find out that sometimes it is impossible to fulfil their wish of swapping half of the prisoners. Whenever this is the case, they have to settle for exchanging as close to one half of the prisoners as possible.

    Input

    On the first line of the input is a single positive integer n, telling the number of test scenarios to follow. Each scenario begins with a line containing two non-negative integers m and r, 1 < m < 200 being the number of prisoners in each of the two prisons, and r the number of dangerous pairs among the prisoners. Then follow r lines each containing a pair xi yi of integers in the range 1 to m,which means that prisoner xi of the first prison must not be placed in the same prison as prisoner yi of the second prison.

    Output

    For each test scenario, output one line containing the largest integer k <= m/2 , such that it is possible to exchange k prisoners of the first prison for k prisoners of the second prison without getting two prisoners of any dangerous pair in the same prison.

    Sample Input

    3
    101 0
    3 3
    1 2
    1 3
    1 1
    8 12
    1 11
    21 3
    1 4
    2 5
    3 5
    4 5
    5 5
    6 6
    7 6
    8 7
    8 8

    Sample Output

    50
    0
    3

    Source



    所有危险囚犯对是可以分割整个二部图为几个集合的,也就是说,比如位于1号监狱的甲如果需要到2号监狱,那么位于2好监狱的所有和甲敌对的囚犯必须得到1号监狱,这样的话可以蔓延这种关系最后形成一个整数对x; y 保证如果甲到2号监狱那么一共要有x个囚犯从1号监狱到2号监狱,而y个囚犯从2号监狱必须得到1号监狱。现在在我们分割二部图为一些整数对后,我们希望选择一部分整数对使它们的和为Sum(x) = Sum(y),并且是小于n=2的最大数。

    dp[ i ][ j ]表示可以用一号监狱的 i 个人跟二号监狱的 j 个人换

    #include <iostream>
    #include <cstdio>
    #include <cstring>

    using namespace std;

    bool mp[222][222],dp[222][222];
    bool prison1[222],prison2[222];
    int r,l,n,m,T;

    void dfs(int x,int tem)
    {
        if(tem==1)
        {
            prison1[x]=true;
        }
        else if(tem==2)
        {
            prison2[x]=true;
        }

        if(tem==1)
        {
            r++;
            for(int i=1;i<=n;i++)
            {
                if(mp[x]&&prison2==false)
                {
                    dfs(i,2);
                }
            }
        }
        else if(tem==2)
        {
            l++;
            for(int i=1;i<=n;i++)
            {
                if(mp[x]&&prison1==false)
                {
                    dfs(i,1);
                }
            }
        }
        return ;
    }

    int main()
    {
        scanf("%d",&T);
    while(T--)
    {
        int i,j,k;
        memset(mp,false,sizeof(mp));
        memset(dp,false,sizeof(dp));
        memset(prison1,false,sizeof(prison1));
        memset(prison2,false,sizeof(prison2));

        int x,y;
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d",&x,&y);
            mp[x][y]=true;
        }

        dp[0][0]=true;

        for(i=1;i<=n;i++)
        {
            if(prison1==false)
            {
                l=0;r=0;
                dfs(i,1);
                for(j=n/2;j>=r;j--)
                {
                    for(k=n/2;k>=l;k--)
                    {
                        if(dp[j-r][k-l]==true)
                            dp[j][k]=true;
                    }
                }
            }
        }

        for(i=1;i<=n;i++)
        {
            if(prison2==false)
            {
                l=0;r=0;
                dfs(i,2);
                for(j=n/2;j>=r;j--)
                {
                    for(k=n/2;k>=l;k--)
                    {
                        if(dp[j-r][k-l]==true)
                            dp[j][k]=true;
                    }
                }
            }
        }

        for(i=n/2;i>=0;i--)
            if(dp)
                break;

        printf("%d ",i);
    }

        return 0;
    }


  • 相关阅读:
    BZOJ 1266: [AHOI2006]上学路线route
    重磅!阿里云Promtheus 正式免费公测
    解锁云原生 AI 技能|在 Kubernetes 上构建机器学习系统
    更新与发展 | Alibaba Cloud Linux 2 特性与开发细节揭秘
    《2019上半年DDoS攻击态势报告》发布:应用层攻击形势依然严峻,海量移动设备成新一代肉鸡
    《2019年上半年Web应用安全报告》发布:90%以上攻击流量来源于扫描器,IP身份不再可信
    并发模式与 RPS 模式之争,性能压测领域的星球大战
    互联网商城的上云改造之旅
    技术人具备“结构化思维”意味着什么?
    弘康人寿基于 RocketMQ 构建微服务边界总线的实践
  • 原文地址:https://www.cnblogs.com/CKboss/p/3350968.html
Copyright © 2011-2022 走看看