Notacja O*

Notacja O, tylko że z dokładnością do wielomianu.

Cykl Hamiltona w grafach subkubicznych

Założenie: . Czy P da się rozszerzyć do cyklu Hamiltona?

function IsHamilton(G, P = {v_1, ...., v_k}){
	if v_k = v(G)
		return v_k -> v_i in E(G); // jesli wszystkie wierzcholki w srodku, zobacz czy istnieje bezposrednie polaczenie zamykajace cykl
		
	else 
		foreach var u in N(v_k) not in P
			if(IsHamilton(G,P + u))
				return true
			
		return false;
}

Jako że ma co najwyżej dwóch sąsiadów nie na ścieżce P, oraz po wykonaniu rekurencji ilość niewykorzystanych wierzchołków maleje o jeden (właśnie go użyliśmy), to z jednego problemu dla mogą powstać co najwyżej dwa podproblemy + sprawdzanie warunków czy wierzchołek jest sąsiadem czy nie w czasie wielomianowym. Niech f to czas wykonania funkcji dla danej ilości niewykorzystanych wierzchołków, czyli n’.

Twierdzenie o rozwiązywaniu rekurencji

Niech f będzie funkcją z N_+ -> R_+ taką że:

gdzie f(1), f(2),…,f(d) <= g(d) dla pewnych stałych d,c1,…,cd oraz niemalejącej funkcji g.

Wówczas f(n) = O*(g(n))
gdzie jest największym pierwiastkiem równania

Wiemy, że spełnia warunek:

Znajdowanie największego zbioru niezależnego

function MaxIs(g){
	if(Delta(G) <= 2){
		zwroc sume ceil(v(C)/2) - ilosc nieparzystych cykli
		
		else 
		v <- wierzcholek o stopniu >= 3
		return max(Maxis(G-N[v]), maxis(G - v));
	}
}

f(n) <= f(n-3) + f(n-1) + O(m) =>
f(n) <= f(n-1) + f(n-3)
co daje

ZAD 1

założenia, G, .

D_min to najmniejszy zbiór dominujący, który udało nam się znaleźć.

D to obecny stan najmniejszego zbioru dominującego, a X to zbiór w którym trzymamy wierzchołki na pewno nie znajdujące się w D. Warunkiem zatrzymania będzie |D| + |X| = n

Możemy również skorzystać z faktu, że jeśli |D| > |D_min|, to możemy uciąć drzewo rekurencji.

function DominatingSet(G, D , X){
	if |D| > |D_min| and |D_min| > 0
		return
	
	Y <- zbiór wierzchołków, które nie są w X ani w D.
	
	if Y = { }
		if każdy wierzchołek z X jest zdominowany
			D_min = D;
		return;
	Niech u to dowolny wierzchołek z Y
	
	DominatingSet(G, D + u, X)
	
	if|N(u) >= 1|{
		v_1 in N(u)
		if v_1 not in D and v_1 not in X
			DominatingSet(G, D + v_1, X + u);
	}
	
	if |N(u) >= 2|
		v_2 in N(u) - v_1
		if v2 not in D and v_2 not in X
			DominatingSet(G, D + v_2, X + u + v_1)
			
	if |N(u)| = 3
		v_3 in N(U) - v_1 - v_2
		if v3 not in D and v3 not in X
			DominatingSet(G, D + v3, X + u + v1 +v2);
}

Daje to wynik O*(1.9276

ZAD 2

Podejście brute force, można zoptymalizować, przez rozpatrzanie tylko opcji:
x = 1,
x = 0, y = 1
x = 0, y = 0, z = 1

function Solve3SAT(R: zbior nie rozwiazanych klauzul){
 
	if R = { }
		return true
	
	T <- nierozstrzygnięta klauzula z R
	if(T nie spełnia klauzuli przy obecnym wartościowaniu)
		return false
	x, y , z <- literaly kasi, ktore nie maja jeszcze wartościowania
	
	x = true
	R` = takie klauzuly, ktore nie maja jeszcze rozwiazan, R - te rozwiazane x = true
	if Solve3SAT(R`)
		return true
	
	x = false, y = true
	R` = klauzule z R bez T oraz tych spelnionych przez y oraz ~x
	
	if Solve3SAT(R`)
		return true
	
	x = false, y = false, z = true;;
	
	R` = klauzula z R bez T oraz tych spelnionych przez z oraz ~y oraz ~x.
	
	
	if Solve3SAT(R`)
		return true
 
 
}

f(n) <= f(n-1) + f(n-2) + f(n-3) + O(n) <- obliczanie R’.

ZAD 3

Wierzchołki z V(G) rozbijamy na 2 (ten o jednym i ten o drugim kolorze). Łączymy rozbite wierzchołki oraz te, które mają ten sam kolor (wierzchołki z których były rozbite muszą sąsiadować ze sobą). G da się pokolorować listowo, gdy G’ jest dwudzielny, oraz każdy wierzchołek z G ma swojego odpowiednika w tej samej klasie dwudzielności.

Dzieje się tak, ponieważ dla każdego wierzchołka klasa X zawiera wierzchołek reprezentujący pokolorowanie v_i na k. Zawiera ona dokładnie jeden wierzchołek v_ik odpowiadajacy v_i ze wzgledu na obecnosc krawedzi laczacych v_ik z vil dla l in L_v_i.

Jednocześnie z dwudzielności wynika, ze dla kazdego koloru k w klasie X nie sąsiadują zadne inne wierzcholki v_ik v_jk takie, że v_iv_j należy do E(G). Kolorowanie jest więc poprawne. Analogicznie jeżeli istnieje kolorowanie grafu, do G’ jest dwudzielny i odpowiednie wierzcholki G’ odpowiadajace temu kolorowaniu tworza klase dwudzielnosci.

ZAD 4

 
function find3Coloring(G: ){
	color = new int[n];
	for(int i = 0; i < n; i++){
		color[i] = -1;
	}
	
	for(int i =0 ; i < n; i++){
		if(color[i] == -1)
			order = BFS(i) <- zwraca kolejnosc od zrodla do kolorowania
			color[i] = 0;
			Color(order, idx)
			
	}
}
 
function Color(order, idx){
	if idx = len(order)
		return true;
	
	v = order[i]
	forbidden = {color[u] : color[u] != -1 and uv in E(G)}
	for c in forbidden
		color[v] = c
		if Color(order, idx+1)
			return true;
		color[v] = none
	
	return false;
}

Zad 5

function podzialnatrojkaty (G){
	if n mod 3 != 0
		return false
		
	
	byMin = new List<int>[n] <- tablica, gdzie byMin[v] to trojkat o najmniejszym indeksie v
	
	foreach {a, b, c} in V, a <= b <= c
		if e(ab) and e(b,c) and e(ac):
			byMin[a].add({a,b,c});
	
	memo = pusta mapa bitowa
	fullset = {0, 1, ..., n-1}
	
	return solve(Fullset)
	
	
	function solve(S){
		if S == { }
			return true
		
		if S in memo:
			return memo[S]
			
			
		v = min(S)
		result = false
		foreach t in byMin[v]:
			if t in S
				if(Solve(S-t))
					result = true;
					break;
		memo[S] = result
		return result;
	}
}

Dowód na podstawie optymalnej podstruktury, jeśli S da się podzielić na na rozłączne trójkąty.

indukcja po |S|
Baza: dla zera zwraca true

Krok Indukcyjny: zakładamy że dla |S| - j działa.
v = min(S). Jeśli S da się rozłożyć na trójkąty, to v gdzieś w nich leży. Wszystkie wierzchołki z t należą do do S, bo if t in S. Jako że min(S) wzięło minimalny dozwolony, do v jest też najmniejsze w t. Jako że wszystkie te wierzchołki należą do S i to trójka, to algorytm wykrył je poprawnie. S-t zwróci poprawnie.

ZAD 6

 
function SteinerTree(G, w, S){
	k = |S|
	
	d = FloydWarshall(G,w)
	
	DP = nowa tablica rozmiaru 2^k z |V|
	DP = tablica[podzbiory S][wierzcholki V]
	for u in S 
		for v in V 
			dp[{u}][v] = d[u,v]
			
	foreach A in S with A.size >= 2 roznaco po wielkosci:
		foreach v in V
			foreach B in A 3^k
				D[A][v] = min(D[A][v] , D[B][v] + D[A-B][v])
				
		foreach v in V;
			foreach u in V:
				D[A][v] = min(D[A][v] , D[A][u] + dist[u][v])
				
	return min(D[S]);
}