TCO '09 Final Easy FractalWheels

問題

方針

まず、hとdを決めると、頂点数と辺の数が定まるので、
グラフの頂点数と辺数からh,dの候補を絞り込む。


h,dが決まると、wheelの「中心」が決まる。
中心からグラフがFractal Wheelかどうかを判定していく。


あるノードに注目すると、まずそのノードが正しい数の子ノードを持っていなくてはならない。
更にその子ノードがきちんと輪を描いているかを見る。


これを再帰的に繰り返してグラフをチェックする。

ソースコード

よくこんなスパゲッティが通るな。。。

int N; bool visit[1000],target[1000];
vector<vi> g;


bool dfs(vi &v,int c,int p,int s,int pt){
	
	//cerr<<"dfs c:"<<c<<" p;"<<p<<" s:"<<s<<" pt;"<<pt<<endl;
	
	int cnt=0;
	rep(i,g[c].size())if(g[c][i]!=p&&target[g[c][i]])cnt++;
	if(p==-1&&cnt!=2||p!=-1&&cnt!=1)return 0;
	
	if(c==s){
		if(pt==v.size())return 1;
		if(pt!=0)return 0;
	}
	
	rep(i,g[c].size())if(g[c][i]!=p&&target[g[c][i]])return dfs(v,g[c][i],c,s,pt+1);
}

bool cycle(vi &v){
	rep(i,N)target[i]=0; rep(i,v.size())target[v[i]]=1;
	return dfs(v,v[0],-1,v[0],0);
}

bool rec(int c,int p,int h,int d,int l){
	
	//cerr<<"c: "<<c<<" p: "<<p<<" h: "<<h<<" d: "<<d<<" l: "<<l<<endl;
	//dbg(g[c].size());
	
	if(l==d+1){
		if(g[c].size()!=3)return 0;
		return 1;
	}
	if(l==0&&g[c].size()!=h)return 0;
	if(0<l&&l<=d&&g[c].size()!=h+3)return 0;
	
	vi v;
	rep(i,g[c].size())if(g[c][i]!=p&&!visit[g[c][i]])v.pb(g[c][i]), visit[g[c][i]]=1;
	//rep(i,v.size())cerr<<v[i]<<(i==v.size()-1?"\n":" ");
	
	if(v.size()!=h||!cycle(v))return 0;
	rep(i,v.size())if(!rec(v[i],c,h,d,l+1))return 0;
	return 1;
}

bool ok(int h,int d){
	
	rep(i,N)if(g[i].size()==h){
		rep(j,N)visit[j]=0; visit[i]=1;
		if(rec(i,-1,h,d,0))return 1;
	}
	return 0;
}

class FractalWheels {
	public:
	vector <int> describeWheel(int N, vector <string> edges) 
	{
		int E=0;
		::N=N;
		g=vector<vi>(N);
		
		string s=accumulate(all(edges),string());
		rep(i,s.size())if(s[i]==',')s[i]=' ';
		stringstream ss(s);
		int a,b;
		while(ss>>a>>b){
			g[a].pb(b); g[b].pb(a); E++;
		}
		
		//dbg(N); dbg(E);
		
		for(int h=3;h<=N-1;h++){
			int n=h+1, e=2*h;
			for(int d=0;;d++){
				
				if(n==N&&e==E && ok(h,d)){
					vi ans;
					ans.pb(d); ans.pb(h);
					return ans;
				}
				
				n=n*h+1; e=e*h+2*h;
				if(n>N||e>E)break;
			}
		}
		
		return vi();
	}
};