码迷,mamicode.com
首页 > 其他好文 > 详细

ZOJ3951 : Independent Set

时间:2017-04-09 23:18:57      阅读:264      评论:0      收藏:0      [点我收藏+]

标签:assert   pac   sse   set   独立   blog   tmp   pen   push   

如果知道了树的形态,那么可以树形DP,每个时刻只需要计算必选根的独立集个数以及必不选根的独立集个数。

那么现在知道独立集个数,要构造出树,可以考虑DP这棵树的形态,然后将之前树形DP的值作为现在DP的状态,即$dp[i][j]$表示必选根的独立集个数为$i$,必不选根的独立集个数为$j$时,树的节点数最少是多少。

那么完成这个DP之后,输出方案只需要沿着最优值来的顺序dfs输出即可。

 

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<time.h>
#include<assert.h>
#include<iostream>
using namespace std;
typedef long long LL;
typedef pair<int,int>pi;
const int Inf=100;
int cnt;
int dp[2020][2020];
struct Node{
	short i,j,x,y;
	Node(){}
	Node(short i,short j,short x,short y):i(i),j(j),x(x),y(y){}
};
Node pre[2020][2020];
void dfs(int u,int x,int y){
	if(x==1&&y==1)return ;
	//printf("x=%d y=%d\n",x,y);
	dfs(u,pre[x][y].i,pre[x][y].j);
	++cnt;
	printf("%d %d\n",u,cnt);
	dfs(cnt,pre[x][y].x,pre[x][y].y);
}
vector<int>V[3000];
int main(){
	int tl=0;
	for(int i=1;i<=2005;i++){
		for(int j=i;j<=2005;j+=i)V[j].push_back(i);
	}
	for(int i=0;i<2020;i++)for(int j=0;j<2020;j++)dp[i][j]=Inf;
	dp[1][1]=1;
	for(int i=1;i<=2005;i++){
		for(int j=1;j<=2005;j++){
			if(dp[i][j]>15)continue;
			for(int y=1;y*i<=2005;y++){
				for(int x=1;(x+y)*j<=2005;x++){
					int tmp=dp[i][j]+dp[x][y];
					int nx=y*i,ny=j*(x+y);
					if(dp[nx][ny]>tmp){
						dp[nx][ny]=tmp;
						pre[nx][ny]=Node(i,j,x,y);
					}
					tl++;
				}
			}
			for(int y=1;y*(i+j)<=2005;y++){
				for(int x=1;x*j<=2005;x++){
					int tmp=dp[i][j]+dp[x][y];
					int nx=j*x,ny=y*(i+j);
					if(dp[nx][ny]>tmp){
						dp[nx][ny]=tmp;
						pre[nx][ny]=Node(x,y,i,j);
					}
					tl++;
				}
			}

		}
	}
	/*
	for(int nx=1;nx<=2005;nx++){
		for(int ny=1;ny<=2005;ny++){
			if(nx==1&&ny==1){dp[nx][ny]=1;continue;}
			for(int it1=0;it1<V[nx].size();it1++){
				for(int it2=0;it2<V[ny].size();it2++){
					int i=V[nx][it1],j=V[ny][it2];
					int y=nx/i,x=ny/j-y;
					if(x>=1&&y>=1&&dp[i][j]+dp[x][y]<dp[nx][ny]){
						dp[nx][ny]=dp[i][j]+dp[x][y];
						pre[nx][ny]=Node(i,j,x,y);
					}
					tl++;
				}
			}
		}
	}
	*/
	//printf("tl=%d\n",tl);
	int _;scanf("%d",&_);
	while(_--){
		int m;
		scanf("%d",&m);
	//for(int tm=1;tm<=2000;tm++){
	//	m=tm+1;
		m++;
		bool flag=0;
		int sx=-1,sy;
		for(int i=0;i<=m;i++){
			if(dp[i][m-i]<=15){
				sx=i;sy=m-i;
				break;
			}
		}
		if(sx<0)puts("-1");
		else{
			printf("%d\n",dp[sx][sy]);
			cnt=1;
			dfs(1,sx,sy);
		}
	}
	return 0;
}

  

ZOJ3951 : Independent Set

标签:assert   pac   sse   set   独立   blog   tmp   pen   push   

原文地址:http://www.cnblogs.com/clrs97/p/6686935.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!