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

    https://cn.vjudge.net/problem/UVA-1627

    题目

    有n(n≤100)个人,把他们分成非空的两组,使得每个人都被分到一组,且同组中的人相互认识。要求两组的成员人数尽量接近。多解时输出任意方案,无解时输出No Solution。

    例如,1认识2, 3, 5;2认识1, 3, 4, 5;3认识1, 2, 5,4认识1, 2, 3,5认识1, 2, 3, 4(注意4认识1但1不认识4),则可以分两组:{1,3,5}和{2,4}。

    题解

    不是互相认识的连边,然后保证一条边的两个人分到两个不同的组

    一个连通分量的人可以存起来……那么类似于poj1417最后的dp部分

    设$dp[i][j]$为前i个连通块,两组人数差为j时是否存在

    因为j可能为负数,不方便迭代,于是改为设$dp[i][100+j]$

    易证若差为j时存在,那么差为-j时也存在,于是最后只用枚举$dp[conn][100..100+n]$是否存在,然后按照dp相反的方向输出解(因为要看每一次的决策是什么)

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    
    #define REP(r,x,y) for(register int r=(x); r<(y); r++)
    #define PER(r,x,y) for(register int r=(x); r>(y); r--)
    #define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
    #define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
    #ifdef sahdsg
    #define DBG(...) printf(__VA_ARGS__)
    #else
    #define DBG(...) (void)0
    #endif
    int n;
    int G[107][107];
    bool tmp[107];
    int v[107],conn=0,r[107];
    int vis[107];
    bool failed;
    int dp[107][207];
    int cho[107];
    inline int signx(int x, int k) {
    	int ans=1;
    	int t=x+1; if(t>n) t=1;
    	vis[x]=k;
    	do {
    		if(G[x][t]) {
    			if(!vis[t])
    				ans-=signx(t,-k);
    			else if(vis[t]!=-k) {
    				failed = true;
    				return 0;
    			}
    		}
    		if(failed) return 0;
    		t++; if(t>n) t=1;
    	} while(t!=x);
    	return ans;
    }
    int ansarr[107][2], ansn[2]={0,0};
    inline void anx(int x, int i) {
    	ansarr[ansn[i]++][i]=x;
    	int t=x+1; if(t>n) t=1;
    	vis[x]=-2;
    	do {
    		if(G[x][t] && vis[t]!=-2) {
    			anx(t, !i);
    		}
    		t++; if(t>n) t=1;
    	} while(t!=x);
    }
    int main() {
    	#ifdef sahdsg
    	freopen("in.txt","r",stdin);
    	#endif
    	int t; scanf("%d", &t);
    	while(0<t--) {
    		scanf("%d", &n); memset(G,0,sizeof G); memset(vis,0,sizeof vis); conn=0;
    		REPE(i,1,n) {
    			int v;
    			memset(tmp,0,sizeof tmp);
    			tmp[i]=1;
    			while(1) {
    				scanf("%d", &v);
    				if(v==0) break;
    				tmp[v]=1;
    			}
    			REPE(j,1,n) if(tmp[j]==0) G[i][j]=G[j][i]=1;
    		}
    		failed = false;
    		int a=0;
    		REPE(i,1,n) {
    			if(!vis[i]) {r[++conn]=i; v[conn]=signx(i,1);}
    			if(failed) {
    				goto _wa;
    			}
    		}
    		#define in(x) ((x)<=200 && (x)>=0)
    		memset(dp,0,sizeof dp);
    		dp[0][100]=1;
    		REPE(i,1,conn) {
    			REPE(j,100-n,100+n) {
    				if(in(j-v[i]) && dp[i-1][j-v[i]]) dp[i][j]=1;
    				else if(in(j+v[i]) && dp[i-1][j+v[i]]) dp[i][j]=1;
    			}
    		}
    		memset(ansn,0,sizeof ansn);
    		for(; a<=n; a++) {
    			if(dp[conn][100+a]) {
    				break;
    			}
    		}
    		PERE(i,conn,1) {
    			if(in(100+a-v[i]) && dp[i-1][100+a-v[i]]) a-=v[i],anx(r[i],0);
    			else if(in(100+a+v[i]) && dp[i-1][100+a+v[i]]) a+=v[i],anx(r[i],1);
    		}
    		#undef in
    		REPE(j,0,1) {
    			printf("%d", ansn[j]);
    			REP(i,0,ansn[j]) {
    				printf(" %d", ansarr[i][j]);
    			}
    			putchar('
    ');
    		}
    		if(t) putchar('
    '); continue;
    		_wa:
    			puts("No solution"); if(t) putchar('
    '); continue;
    	}
    	return 0;
    }
    
  • 相关阅读:
    创建Android项目时出错——No resource found that matches the given name 'Theme.AppCompat.Light'
    Java、Android 开发环境搭建
    tomcat7的安装与配置、及Servlet部署
    让实体对象自行决定留存操作类型(增删改)
    聚合体
    PowerDesigner15中定义varbinary(max)列
    Pig limit用法举例
    Pig join用法举例
    Pig distinct用法举例
    Pig group用法举例
  • 原文地址:https://www.cnblogs.com/sahdsg/p/10601609.html
Copyright © 2011-2022 走看看