POJ 1112 Team Them Up!

引用discuss里的一句话,好辣的一道题目。。。

一定要注意认识的关系不是互相的,先建图,把不是互相认识的人连边,然后二分图染色,把原图分成m个块,再用类似背包的东西分f[i][j][k]表示前i个块,team1有j个人,team2有k个人能否实现,注意记录一下路径,然后递归输出就可以了,题目不算很难,但是细节比较多,涉及到的东西也挺多,挺容易出错的。。。

 

 

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<stack>
  7 #include<queue>
  8 #include<map>
  9 #include<cstdlib>
 10 #include<cmath>
 11 using namespace std;
 12 #define ll long long
 13 #define pb push_back
 14 const int maxn = 102;
 15 vector<int>q[maxn];
 16 bool s[maxn];
 17 int a[maxn][4];
 18 vector<int>b[maxn][4];
 19 int t[maxn],g[maxn][maxn][maxn];
 20 int m,n;
 21 bool v[maxn][maxn],e[maxn][maxn];
 22 bool f[maxn][maxn][maxn];
 23 void solve(int x,int y)
 24 {
 25     for (int i = 0; i < q[x].size(); i++)
 26         if (s[q[x][i]] == 0)
 27     {
 28         s[q[x][i]] = 1;
 29         a[m][y]++;
 30         b[m][y].pb(q[x][i]);
 31         solve(q[x][i],3 - y);
 32     }
 33 }
 34 void dfs(int now,int x,int y)
 35 {
 36     if (now == 0) return;
 37     t[now] = g[now][x][y];
 38     if (t[now] == 1) dfs(now - 1,x - a[now][1],y - a[now][2]);
 39     else dfs(now - 1,x - a[now][2],y - a[now][1]);
 40 }
 41 bool check(int x,int y)
 42 {
 43     for (int i = 0; i < b[x][y].size(); i++)
 44         for (int j = 0; j < b[x][y].size(); j++)
 45           if (b[x][y][i] != b[x][y][j] && e[b[x][y][i]][b[x][y][j]]) return 1;
 46     return 0;
 47 }
 48 int main()
 49 {
 50     while (scanf("%d",&n) != EOF)
 51     {
 52         for (int i = 1; i <= n; i++) q[i].clear();
 53         memset(v,0,sizeof(v));
 54         memset(e,0,sizeof(e));
 55         int x;
 56         for (int i = 1; i <= n; i++)
 57         {
 58             while (scanf("%d",&x) && x != 0) v[i][x] = 1;
 59         }
 60         //for (int i = 1; i <= n;i++)
 61             //for (int j = 1; j <= n; j++) if (v[i][j]) cout<<i<<" "<<j<<endl;
 62         //return 0;
 63         for (int i = 1; i <= n; i++)
 64             for (int j = i + 1; j <= n; j++)
 65         {
 66             if (v[i][j] && v[j][i]) continue;
 67             q[i].pb(j);
 68             q[j].pb(i);
 69             e[i][j] = e[j][i] = 1;
 70         }
 71         /*for (int i = 1; i<= n; i++)
 72         {
 73             cout<<i<<" ";
 74             for (int j = 0; j < q[i].size(); j++) cout<<q[i][j]<<" ";
 75             cout<<endl;
 76         }*/
 77         //return 0;
 78         memset(s,0,sizeof(s));
 79         memset(s,0,sizeof(s));
 80         memset(a,0,sizeof(a));
 81         m = 0;
 82         for (int i = 1; i <= n; i++)
 83             for (int j = 1; j <= 2; j++) b[i][j].clear();
 84         for (int i = 1; i <= n; i++)
 85           if (s[i] == 0)
 86         {
 87             s[i] = 1;
 88             m++;
 89             a[m][1]++;
 90             b[m][1].pb(i);
 91             solve(i,2);
 92         }
 93         bool flag = 0;
 94         for (int i = 1; i <= m; i++)
 95         {
 96             if (check(i,2) || check(i,1))
 97             {
 98                 flag = 1;
 99                 break;
100             }
101         }
102         if (flag)
103         {
104              puts("No solution");
105             continue;
106         }
107         memset(f,0,sizeof(f));
108         memset(g,0,sizeof(g));
109         f[0][0][0] = 1;
110         //return 0;
111         for (int i = 1; i <= m; i++)
112             for (int j = 0; j <= n; j++)
113                 for (int k = 0; k <= n; k++)
114                     if (j + k <= n)
115             {
116                 if (j - a[i][1] >= 0 && k - a[i][2] >= 0 && f[i - 1][j - a[i][1]][k - a[i][2]])
117                 {
118                     f[i][j][k] = 1;
119                     g[i][j][k] = 1;
120                 }
121                 if (j - a[i][2] >= 0 && k - a[i][1] >= 0 && f[i - 1][j - a[i][2]][k - a[i][1]])
122                 {
123                     f[i][j][k] = 1;
124                     g[i][j][k] = 2;
125                 }
126             }
127         int maxx = 10000,fir = 0,sec = 0;
128         for (int i = 1; i <= n - 1; i++)
129         {
130               int j = n - i;
131               if (f[m][i][j] && maxx > abs(i - j))
132               {
133                   maxx = abs(i - j);
134                   fir = i; sec = j;
135               }
136         }
137         memset(t,0,sizeof(t));
138         dfs(m,fir,sec);
139         memset(s,0,sizeof(s));
140         int ans = 0;
141         for (int i = 1; i <= m; i++)
142             if (t[i] == 1)
143             {
144                 ans = ans + b[i][1].size();
145                 for (int j = 0; j < b[i][1].size(); j++) s[b[i][1][j]] = 1;
146             }
147             else
148             {
149                 ans = ans + b[i][2].size();
150                 for (int j = 0; j < b[i][2].size(); j++) s[b[i][2][j]] = 1;
151             }
152         if (ans == n || ans == 0)
153         {
154             puts("No solution");
155             continue;
156         }
157         printf("%d",ans);
158         for (int i = 1; i <= n; i++)
159             if (s[i]) printf(" %d",i);
160         printf("\n");
161         printf("%d",n - ans);
162         for (int i = 1; i <= n; i++)
163             if (!s[i]) printf(" %d",i);
164         printf("\n");
165     }
166     return 0;
167 }
View Code

 

转载于:https://www.cnblogs.com/yuhao1994/p/3578149.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值