poj 1636 动态规划

【题意】

有两个监狱,每个监狱里面有n个囚犯,现在希望交换n/2对囚犯。但是考虑有一些原本在不同监狱的囚犯对在一起是很危险的,所以希望经过交换后他们还是不在一个监狱里面。那么如果保证这个条件,希望尽可能多的交换囚犯。

【题解】

和team them up这道题类似。

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

【教训】

我原先做过team them up这道题,但做这题是却以为用二分图最大独立集来搞,完全飞机了。

【代码】

#include <iostream>
#include <vector>
using namespace std;
const int maxn=405;

vector<int> a[maxn];
int p[maxn],q[maxn];
bool f[maxn][maxn],v[maxn];
int n,m,b,w,tot,mm;

void dfs(int x)
{
     int i,y;
     v[x]=true;
     if (x<=n) w++;
     else b++;
     for (i=0;i<a[x].size();i++)
     {
         y=a[x][i];
         if (v[y]) continue;
         dfs(y);
     }
}

int main()
{
    freopen("pin.txt","r",stdin);
    freopen("pou.txt","w",stdout);
    int i,j,k,cc;
    scanf("%d",&cc);
    while (cc--)
    {
          scanf("%d%d",&n,&m);
          for (i=0;i<=2*n;i++)
              a[i].clear();
          memset(f,0,sizeof(f));
          memset(v,0,sizeof(v));
          tot=0;
          for (i=1;i<=m;i++)
          {
              int x,y;
              scanf("%d%d",&x,&y);
              a[x].push_back(y+n);
              a[y+n].push_back(x);
          }
          for (i=1;i<=n+n;i++)
          if (!v[i])
          {
             b=w=0;
             dfs(i);
             p[++tot]=w;q[tot]=b;
          }
          f[0][0]=true;
          mm=0;
          for (i=1;i<=tot;i++)
          {
              for (j=n/2;j>=p[i];j--)
                  for (k=n/2;k>=q[i];k--)
                  {
                      if (f[j-p[i]][k-q[i]])
                         f[j][k]=true;
                  }
              mm=max(mm+p[i],mm+q[i]);
          }
          for (i=n/2;i>=0;i--)
              if (f[i][i]) break;
          cout << i << endl;
    }
    return 0;
}

    原文作者:动态规划
    原文地址: https://blog.csdn.net/ascii991/article/details/7516548
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞