• UVa1627


    这道题题意就不说了,说一下思路:

    我们发现互相不认识的人一定不会分到同一组,所以我们将互相不认识的人两两之间连一条线段,这样我们就得到了连通图,经过

    观察,我们发现将不认识的人分开这样就得到了二分图,后面我们需要通过dp使得最后两组的人数相同,这样我们就得到了该问题的解法。

    下面是代码:

    // UVa 1627 
    // 二分图 + dp
    #include <cstdio> 
    #include <cstring> 
    #include <vector> 
    #include <algorithm> 
    using namespace std; 
    
    const int maxn = 100 + 10; 
    
    int n, G[maxn][maxn], color[maxn], diff[maxn], cc; 
    vector<int> team[maxn][2]; 
    
    bool dfs(int u, int c) {
      color[u] = c; 
      team[cc][c-1].push_back(u);
      for (int v = 0; v < n; ++v)
        if (u != v && !(G[u][v] && G[v][u])) {
          if (color[v] > 0 && color[v] == color[u]) return false; 
          if (!color[v] && !dfs(v, 3-c)) return false; 
        }
      return true; 
    }
    
    bool build_graph() {
      memset(color, 0, sizeof(color)); 
      cc = 0; 
      for (int i = 0; i < n; ++i) 
        if (!color[i]) {
          team[cc][0].clear();
          team[cc][1].clear(); 
          if (!dfs(i, 1)) return false; 
          diff[cc] = team[cc][0].size() - team[cc][1].size(); 
          cc++;    
        }
      return true; 
    }
    
    int d[maxn][maxn*2]; 
    
    void print(int ans) {
      vector<int> team1, team2; 
      for (int i = cc-1; i >= 0; --i) {
        int t; 
        if (d[i][ans-diff[i]+n]) { t = 0; ans -= diff[i]; } 
        else { t = 1; ans += diff[i]; } 
        for (int j = 0; j < team[i][t].size(); ++j) 
          team1.push_back(team[i][t][j]); 
        for (int j = 0; j < team[i][1^t].size(); ++j)
          team2.push_back(team[i][1^t][j]); 
      }
      printf("%d", team1.size());
      for (int i = 0; i < team1.size(); ++i) printf(" %d", team1[i]+1); 
      printf("
    ");
      
      printf("%d", team2.size()); 
      for (int i = 0; i < team2.size(); ++i) printf(" %d", team2[i]+1); 
      printf("
    ");
    }
    
    void dp() {
      memset(d, 0, sizeof(d));
      d[0][0+n] = 1; 
      for (int i = 0; i < cc; ++i) 
        for (int j = -n; j <= n; ++j) if (d[i][j+n]) {
          d[i+1][j+diff[i]+n] = 1; 
          d[i+1][j-diff[i]+n] = 1;    
        } 
      for (int ans = 0; ans <= n; ++ans) {
        if (d[cc][ans+n]) { print(ans); return; }
        if (d[cc][-ans+n]) { print(-ans); return; }   
      }
    }
    
    int main() { 
      int t; 
      scanf("%d", &t);
      while (t--) {
        scanf("%d", &n); 
        memset(G, 0, sizeof(G)); 
        for (int u = 0; u < n; ++u) {
          int v; 
          while (scanf("%d", &v) == 1 && v) G[u][v-1] = 1; 
        }
        
        if (n == 1 || !build_graph()) printf("No solution
    "); 
        else dp(); 
        
        if (t) printf("
    "); 
      }
      return 0;
    }
  • 相关阅读:
    vmware12中安装MAC OS X 10.10
    AOL search
    [python]错误检测及异常处理try-except
    [推荐]
    [python]打开文件操作open用法
    MAC使用小技巧
    [推荐]
    [python]python中的if, while, for
    [python]python字典
    [python]python列表、元组
  • 原文地址:https://www.cnblogs.com/yifeiWa/p/11293656.html
Copyright © 2020-2023  润新知