记录编号 130493 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队 2012] 道路染色 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.037 s
提交时间 2014-10-22 15:44:46 内存使用 14.56 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int SIZEN=320,INF=0x7fffffff/2;
class KM_Solver{
public:
	//求最大匹配
	int N,m,n;//左m右n,一共是N
	//1~m是左半边,m+1~N是右半边
	int (*c)[SIZEN];//c[SIZEN][SIZEN],切记保持第二维的长度
	int slack[SIZEN];
	bool visit[SIZEN];
	int match[SIZEN];
	int label[SIZEN];
	void assign(int a,int b,int A[SIZEN][SIZEN]){m=a,n=b,N=a+b;c=A;}
	bool findpath(int u){
		visit[u]=true;
		for(int i=m+1;i<=N;i++){
			if(visit[i]||c[u][i]==-INF) continue;
			int t=label[u]+label[i]-c[u][i];
			if(!t){
				visit[i]=true;
				if(match[i]==-1||findpath(match[i])){
					match[i]=u;
					return true;
				}
			}
			else if(slack[i]>t) slack[i]=t;
		}
		return false;
	}
	int calc(int a,int b,int A[SIZEN][SIZEN]){
		assign(a,b,A);
		memset(match,-1,sizeof(match[0])*(N+1));
		for(int i=1;i<=m;i++){
			label[i]=-INF;
			for(int j=m+1;j<=N;j++) label[i]=max(label[i],c[i][j]);
		}
		for(int i=m+1;i<=N;i++) label[i]=0;
		for(int i=1;i<=m;i++){
			while(true){
				memset(visit,0,sizeof(visit[0])*(N+1));
				for(int j=m+1;j<=N;j++) slack[j]=INF;
				if(findpath(i)) break;
				int d=INF;
				for(int j=m+1;j<=N;j++) if(!visit[j]) d=min(d,slack[j]);
				for(int j=1;j<=m;j++) if(visit[j]) label[j]-=d;
				for(int j=m+1;j<=N;j++) if(visit[j]) label[j]+=d;
			}
		}
		int ans=0;
		for(int i=m+1;i<=N;i++){
			if(match[i]!=-1) ans+=c[match[i]][i];
		}
		return ans;
	}
}S;
int N;
vector<int> c[SIZEN];
vector<int> son[SIZEN];
int father[SIZEN]={0};
bool vis[SIZEN][SIZEN]={0};
int f[SIZEN][SIZEN];
int A[SIZEN][SIZEN]={0};
int a[SIZEN]={0};
void DFS(int x){
	for(int i=0;i<c[x].size();i++){
		int u=c[x][i];
		if(u==father[x]) continue;
		son[x].push_back(u);
		father[u]=x;DFS(u);
	}
	int deg=son[x].size();
	if(!deg) return;
	for(int i=1;i<=deg;i++){
		int u=son[x][i-1];
		for(int j=1;j<N;j++){
			if(f[u][j]!=INF) A[i][deg+j]=-(f[u][j]+j);
			else A[i][deg+j]=-INF;
		}
	}
	int tmp=-S.calc(deg,N-1,A);
	if(!father[x]){
		f[x][0]=tmp;
		return;
	}
	for(int i=1;i<N;i++){
		if(S.match[deg+i]==-1) f[x][i]=tmp,vis[x][i]=true;
	}
	for(int i=1;i<N;i++){
		if(vis[x][i]) continue;
		vis[x][i]=true;
		//计算f[x][i],即i不能选
		for(int j=1;j<=deg;j++) a[j]=A[j][deg+i],A[j][deg+i]=-INF;
		f[x][i]=-S.calc(deg,N-1,A);
		for(int j=1;j<=deg;j++) A[j][deg+i]=a[j];
	}
}
void read(void){
	scanf("%d",&N);
	int a,b;
	for(int i=1;i<N;i++){
		scanf("%d%d",&a,&b);
		c[a].push_back(b);
		c[b].push_back(a);
	}
}
int main(){
	freopen("nt2012_coloring.in","r",stdin);
	freopen("nt2012_coloring.out","w",stdout);
	read();
	DFS(1);
	printf("%d\n",f[1][0]);
	return 0;
}