zoukankan      html  css  js  c++  java
  • uva1627 Team them up!

    注意这题要求互相认识
    不认识的人之间连一条线
    一个人在组1,那么不认识(互相认识)的人就在组0;同时这些人不认识的人就在组1.每个联通分量都可以独立推导,遇到矛盾则无解
    一个联通分量有一个核心,其他的点是分支
    我感觉紫书写的样例又是有点问题,应该是4在0,那么135在1,反正则反;而不是1在0,345在1
    然后一个联通分量的核心在一组,分支就在另一组;
    设0组比1组多d,就对应d加一个或者减一个值
    相当于背包

    矛盾状况就是任意个联通分量不能二分染色

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 100 + 5;
    
    int n, G[maxn][maxn], color[maxn], diff[maxn], cc;
    vector<int> team[maxn][2]; // team[cc][c] is the list of people in connected-component cc, color c
    
    // returns false if not bipartite graph
    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])) { // u and v 不互相认识
          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; // current connected-component
      for(int i = 0; i < n; i++)
        if(!color[i]) {
          team[cc][0].clear();  //存染成1的
          team[cc][1].clear();  //染成2的
          if(!dfs(i, 1))
            return false;
          diff[cc] = team[cc][0].size() - team[cc][1].size();
          cc++;
        }
    
      return true;
    }
    
    // d[i][j+n] = 1 iff we can arrange first i cc so that team 1 has j more people than team 2.
    int d[maxn][maxn*2], teamno[maxn];
    
    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;
      cin >> T;
      while(T--) {
        cin >> n;
        memset(G, 0, sizeof(G));
        for(int u = 0; u < n; u++) {
          int v;
          while(cin >> v && v) G[u][v-1] = 1;   //认识
        }
    
        if(n == 1 || !build_graph())
            cout << "No solution
    ";
        else
            dp();
            cout << "
    ";
      }
      return 0;
    }
  • 相关阅读:
    刷盘子的中国
    重温一些文章
    小心时间悄悄流失
    WebService笔记一
    JavaScript类型转换方法及需要注意的问题
    TSQL查询 点滴 1
    介绍几款浏览器兼容性测试工具
    [推荐] jQuery 表格插件汇总
    学会总结,学会关注细节,学会拥有一颗平静的心。
    Open Source Web Design!
  • 原文地址:https://www.cnblogs.com/lqerio/p/9800741.html
Copyright © 2011-2022 走看看