jzoj3782 【NOIP2014模拟8.17】组队 (特殊情况的2sat,dp)
2018-02-02 15:36
651 查看
题面
你的任务是将一群人分到两个队伍中,使得:1、每个人都属于一个队伍。
2、每个队伍至少有一个人。
3、每个队伍的任意一个人都认识其他人。
4、两支队伍的人数尽可能接近。
这个任务可能有多组解,你可以输出任意一种。
注意:认识是单向的且没有传递性。
对于分值为 30%的数据,N <= 15
对于剩余分值为 70%的数据,N <= 100
2-SAT?
一开始想复杂了,一直在回忆2-sat怎么打。 其实没有必要。显然可以先找出不能在同一集合的一些(x,y)
开始0,1染色判方案。
找出所有相对集合A:B,只要A,B颜色不同就行。
题目要求尽可能接近,那就
用个dp染色求方案即可。 (决策:A放黑或B放黑)
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> #include <cstdlib> using namespace std; const int N=101; int n,bz1 ,bz ,f ,o; pair<int,int> pre ; int un ; int ans,at ; int g [2],h; bool cmp(int x,int y) {return un[x][0]<un[y][0];} int cnt1,cnt2,stm; int tm1 ,tm2 ; void dfs(int x) { for (int i=1; i<=un[x][0]; i++) { int y=un[x][i]; if (bz[y]!=0) { if (bz[y]==bz[x]) { printf("-1\n"); exit(0); } } else { bz[y]=(bz[x]==stm)?stm+1:stm; if (bz[y]==stm) cnt1++; else cnt2++; dfs(y); } } } int main() { //freopen("3.in","r",stdin); cin>>n; for (int i=1; i<=n; i++) { memset(bz,0,sizeof bz); int x; while (scanf("%d",&x),x) bz1[i][x]=1; } for (int i=1; i<=n; i++) { for (int j=1; j<=n; j++) if (i!=j && (!bz1[i][j] || !bz1[j][i])) un[i][++un[i][0]]=j; } for (int i=1; i<=n; i++) if (!bz[i]) { stm+=2; cnt2=0,cnt1=1,bz[i]=stm,dfs(i); g[++h][0]=cnt1,g[h][1]=cnt2; at[h]=stm; } f[0][0][0]=1; for (int i=1; i<=h; i++) { for (int a=0; a<=n; a++) for (int b=0; b<=n; b++) { if (a+g[i][0]<=n && b+g[i][1] <=n) { f[i][a+g[i][0]][b+g[i][1]]|=f[i-1][a][b]; if (f[i-1][a][b]) { pre[i][a+g[i][0]][b+g[i][1]]=make_pair(a,b); } } if (a+g[i][1]<=n && b+g[i][0] <=n) { f[i][a+g[i][1]][b+g[i][0]]|=f[i-1][a][b]; if (f[i-1][a][b]) { pre[i][a+g[i][1]][b+g[i][0]]=make_pair(a,b); } } } } for (int i=n/2; i; i--) if (f[h][i][n-i]) { int x=i,y=n-i; for (int j=h; j; j--) { int xx=pre[j][x][y].first,yy=pre[j][x][y].second; int k1=at[j],k2=k1+1; if (x-xx==g[j][1]) swap(k1,k2); for (int z=1; z<=n; z++) if (bz[z]==k1) tm1[++tm1[0]]=z; else if (bz[z]==k2) tm2[++tm2[0]]=z; x=xx,y=yy; } for (int i=0; i<=tm1[0]; i++) printf("%d ",tm1[i]); printf("\n"); for (int i=0; i<=tm2[0]; i++) printf("%d ",tm2[i]); return 0; } }
相关文章推荐
- JZOJ 3782. 【NOIP2014模拟8.17】组队
- JZOJ3782. 【NOIP2014模拟8.17】组队
- [jzoj]3889. 【NOIP2014模拟10.25B组】序列问题(DP的各种方法+细节+详细分析)
- jzoj3782 [NOIP2014模拟8.17] 组队
- jzoj3927【NOIP2014模拟11.6】可见点数(欧拉函数)
- JZOJ 3809. 【NOIP2014模拟8.25】设备塔
- JZOJ 3775. 【NOIP2014模拟8.15】因子的排列
- jzoj. 3838. 【NOIP2014模拟9.14】Super Big Stupid Cross
- JZOJ 3822. 【NOIP2014模拟9.9】逆光
- JZOJ 3823【NOIP2014模拟9.9】遇见
- 【jzoj5289】【NOIP2017提高组A组模拟8.17】【偷笑】【数据结构】
- JZOJ-senior-3910. 【NOIP2014模拟11.1A组】Idiot 的间谍网络
- jzoj3796 【NOIP2014模拟8.21】议案决定
- JZOJ 3813. 【NOIP2014模拟9.7】我要的幸福
- JZOJ 3809 【NOIP2014模拟8.25】设备塔
- jzojNOIP2014模拟 8.14总结
- jzoj[3521]. 【NOIP2013模拟11.7B组】道路覆盖(cover) (状压DP)
- jzoj. 3889. 【NOIP2014模拟10.25B组】序列问题
- JZOJ 3809. 【NOIP2014模拟8.25】设备塔
- JZOJ 3824【NOIP2014模拟9.9】渴