现在的位置: 首页 > 综合 > 正文

UVA – 1627

2019年04月03日 ⁄ 综合 ⁄ 共 2430字 ⁄ 字号 评论关闭

显然本题要先按不认识重新建立边(两者u认识v 但 v不认识u 也算不认识) 然后二分匹配,匹配成功,即可分为两组;

接下来的问题就是背包问题了,选每个连通分量里被1着色的部分,则该连通分量剩下的人只能在另一组,这样可看做 第一组比第二组多增加(num(1) - num(2)) 个人;这样

问题就是对所有连通分量的背包选择;

边界注意

    #include <map>  
    #include <cstdio>  
    #include <vector>  
    #include <cstdlib>  
    #include <cstring>  
    #include <iostream>  
    #include <algorithm>  
    using namespace std;  
    const int maxn = 105;  
    vector<int> son[maxn],bag,st[maxn][2];  
    bool vis[maxn],G[maxn][maxn];  
    int color[maxn],n;  
    bool bipartite(int u,int cnt){  
    for(int i=1;i<=n;i++)if(G[u][i]){  
          int v = i;  
          if(color[v]){  
             if(color[v] == color[u]) return false;  
             continue;  
          }  
          color[v] = 3 - color[u];  
          st[cnt][color[v]-1].push_back(v);  
          if(!bipartite(v,cnt)) return false;  
    }  
    return true;  
    }  
    const int ADD = 101;  
    int d[maxn][maxn*2+4][2];  
    bool VIS[maxn][maxn*2+4][2];  
    int dp(int i,int j,int k){  
    if(VIS[i][j][k]) return d[i][j][k];  
    VIS[i][j][k] = true;  
      
    int& ans = d[i][j][k];  
    if(i==bag.size() - 1) {return d[i][j][k] =0;}  
    int now = j - ADD;  
    int ans1 = dp(i+1,ADD+(now-bag[i+1]),0) + bag[i+1];  
    int ans2 = dp(i+1,ADD+(now+bag[i+1]),1) - bag[i+1];  
    ans = abs(now - ans1) < abs(now - ans2) ? ans1 : ans2;  
    return ans;  
    }  
    vector<int> ans;  
    void print_ans(int i,int j,int k){  
    if(i == bag.size() - 1)  return ;  
    if(d[i][j][k] == dp(i+1,ADD+(j-ADD-bag[i+1]),0) + bag[i+1]){  
           for(int g=0;g<st[i+1][0].size();g++)  
               ans.push_back(st[i+1][0][g]);  
               print_ans(i+1,ADD+(j-ADD-bag[i+1]),0);  
    }  
    else {  
        for(int g=0;g<st[i+1][1].size();g++)  
               ans.push_back(st[i+1][1][g]);  
               print_ans(i+1,ADD+(j-ADD+bag[i+1]),1);  
    }  
    }  
    int main(){  
        //freopen("input.txt","r",stdin);  
        int T,kase=0;  
        scanf("%d",&T);  
        while(T--){  
            if(kase++) printf("\n");  
            scanf("%d",&n);  
            for(int i=1;i<=n;i++) son[i].clear();  
            for(int i=1;i<=n;i++){  
                 int x;  
                 while(scanf("%d",&x)&&x){  
                      son[i].push_back(x);  
                 }  
            }  
            memset(G,false,sizeof(G));  
            for(int i=1;i<=n;i++){  
                  memset(vis,false,sizeof(vis));  
                  for(int j=0;j<son[i].size();j++) vis[son[i][j]] = true;  
                  for(int j=1;j<=n;j++)if(j!=i){  
                       if(!vis[j]){  
                          G[i][j] = G[j][i] = true;  
                       }  
                  }  
            }  
            memset(color,0,sizeof(color));  
            bool flag=true;  
            bag.clear(); bag.push_back(0);  
            for(int i=1;i<=n;i++){  
                 if(!color[i]){  
                      int cnt = bag.size();  
                      st[cnt][0].clear();  
                      st[cnt][1].clear();  
                      color[i] = 1; st[cnt][0].push_back(i);  
                        if(!bipartite(i,cnt)){  
                             flag=false; break;  
                        }  
                        int c1=st[cnt][0].size();  
                        int c2=st[cnt][1].size();  
                        bag.push_back(c1 - c2);  
                    }  
                 }  
            if(!flag){  
                  printf("No solution\n");  continue;  
            }  
            memset(VIS,false,sizeof(VIS));  
            dp(0,ADD,0);  
            ans.clear(); print_ans(0,ADD,0);  
            memset(vis,false,sizeof(vis));  
            printf("%d",ans.size());  
            for(int i=0;i<ans.size();i++) {printf(" %d",ans[i]);  vis[ans[i]]=1;}  
            printf("\n");  
            printf("%d",n-ans.size());  
            for(int i=1;i<=n;i++) if(!vis[i]) printf(" %d",i);  
            printf("\n");  
        }  
        return 0;  
    }  
    /* 
    2 
    5 
    3 4 5 0 
    1 3 5 0 
    2 1 4 5 0 
    2 3 5 0 
    1 2 3 4 0 
    5 
    2 3 5 0 
    1 4 5 3 0 
    1 2 5 0 
    1 2 3 0 
    4 3 2 1 0 
    */  

抱歉!评论已关闭.