Generate WORKING Manim code for Scene 1.

IMPLEMENTATION: ```python
from manim import *

class DijkstraIntro(Scene):
    def construct(self):
        # Layout Plan:
        # 1. Title: Text - .to_edge(UP, buff=0.5) - Introduce scene topic
        # 2. Main equation (or main statement): Text - .shift(UP * 1.5) - Define purpose of Dijkstra's algorithm
        # 3. Secondary text: Text - .shift(DOWN * 1.5) - Explain goal in simple terms
        # 4. Left elements: Diagram of simple weighted graph (Circles, Lines, Arrows, Text) - .shift(LEFT * 2.5)
        # 5. Right elements: Highlight starting node (SurroundingRectangle) - .shift(RIGHT * 2.5)

        # Step 1: Title
        title = Text("Understanding Dijkstra's Algorithm", color=WHITE).to_edge(UP, buff=0.5)
        self.play(Write(title), run_time=2)

        # Step 2: Main equation/statement - purpose of algorithm
        main_statement = Text(
            "Find shortest paths from a start node to all others\nin a weighted graph with non-negative edges.",
            color=WHITE
        ).shift(UP * 1.5)
        self.play(Write(main_statement), run_time=3)

        # Step 3: Secondary text - explain goal
        secondary_text = Text(
            "Goal: Determine minimum distance from start to every node.",
            color=WHITE
        ).shift(DOWN * 1.5)
        self.play(Write(secondary_text), run_time=2)

        # Pause briefly before next step
        self.wait(1)

        # Step 4: Show simple weighted graph on left side
        # Create nodes (Dots with labels)
        # Positions relative to LEFT * 2.5
        graph_center = LEFT * 2.5

        # Nodes positions (relative to graph_center)
        node_positions = {
            "A": graph_center + UP * 1,
            "B": graph_center + LEFT * 1 + DOWN * 0.5,
            "C": graph_center + RIGHT * 1 + DOWN * 0.5,
            "D": graph_center + DOWN * 1.5,
        }

        nodes = {}
        labels = {}
        for name, pos in node_positions.items():
            dot = Dot(pos, color=BLUE)
            label = Text(name, font_size=24, color=WHITE).next_to(dot, DOWN)
            nodes[name] = dot
            labels[name] = label

        # Edges with weights (Lines + MathTex for weights)
        edges_info = [
            ("A", "B", 4),
            ("A", "C", 2),
            ("B", "C", 5),
            ("B", "D", 10),
            ("C", "D", 3),
        ]

        edges = []
        weights = []
        for start, end, w in edges_info:
            line = Line(nodes[start].get_center(), nodes[end].get_center(), color=WHITE)
            # Place weight label at midpoint shifted slightly UP
            mid = (nodes[start].get_center() + nodes[end].get_center()) / 2 + UP * 0.2
            weight_label = MathTex(str(w), color=YELLOW).move_to(mid)
            edges.append(line)
            weights.append(weight_label)

        # Group graph elements
        graph_elements = VGroup(*nodes.values(), *labels.values(), *edges, *weights)

        self.play(
            *[Create(mob) for mob in edges],
            *[FadeIn(dot) for dot in nodes.values()],
            *[Write(label) for label in labels.values()],
            *[Write(w) for w in weights],
            run_time=4
        )

        # Step 5: Highlight starting node on right side
        # Starting node: "A"
        start_node_pos = RIGHT * 2.5 + UP * 1
        start_node_dot = Dot(start_node_pos, color=BLUE)
        start_node_label = Text("Start Node: A", color=WHITE).next_to(start_node_dot, DOWN)
        start_node_rect = SurroundingRectangle(start_node_dot, color=RED, buff=0.15)

        self.play(
            FadeIn(start_node_dot),
            Write(start_node_label),
            Create(start_node_rect),
            run_time=3
        )

        # Pause to let user observe
        self.wait(2)

        # Cleanup highlights (fade out rectangle and start node elements)
        self.play(FadeOut(start_node_rect), FadeOut(start_node_dot), FadeOut(start_node_label), run_time=1.5)

        # Cleanup graph elements
        self.play(
            *[FadeOut(mob) for mob in graph_elements],
            run_time=2
        )

        # Cleanup secondary text
        self.play(FadeOut(secondary_text), run_time=1)

        # Keep title and main statement visible for transition text
        transition_text = Text(
            "Having understood what the algorithm aims to solve,\n"
            "next we explore how it systematically finds the shortest paths step-by-step.",
            color=WHITE
        ).shift(DOWN * 1.5)

        self.play(Write(transition_text), run_time=3)

        # Final pause
        self.wait(2)

        # Final cleanup: fade out everything except title and main statement
        self.play(FadeOut(transition_text), run_time=1)
        self.wait(1)
```
---

### Explanation:

- **Title**: Positioned `.to_edge(UP, buff=0.5)` per requirement.
- **Main statement**: Positioned `.shift(UP * 1.5)` (upper center).
- **Secondary text**: Positioned `.shift(DOWN * 1.5)` (lower center).
- **Graph**: Entire graph group shifted `.shift(LEFT * 2.5)` by placing nodes relative to `LEFT * 2.5`.
- **Start node highlight**: Positioned `.shift(RIGHT * 2.5)` by placing start node dot and label relative to `RIGHT * 2.5`.
- All elements fit within screen bounds.
- Colors restricted to BLUE (nodes), RED (highlight rectangle), WHITE (text, edges), YELLOW (weights).
- Animations restricted to Write, Create, FadeIn, FadeOut.
- Cleanup rules followed: fade out highlights and old descriptions, keep main statement and title visible until final cleanup.
- No shifts beyond +/-3 in any direction.
- Simple weighted graph with clear labels and weights.
- Transition text appears at the bottom center after graph and highlights fade out.

This plan strictly follows the instructions and positioning rules.
PATTERN: function_graph

CRITICAL CONSTRAINTS:
1. Use ONLY these objects: Text, MathTex, Axes, Circle, Rectangle, Line, Arrow, Dot, SurroundingRectangle, VGroup
2. Use ONLY these animations: Write, Create, FadeIn, FadeOut 
3. Use ONLY these colors (no quotes): BLUE, RED, GREEN, YELLOW, WHITE, ORANGE, PURPLE
4. NO undefined objects like VideoFile, Slider, ImageMobject
5. NO Unicode characters - use LaTeX: \sqrt{} not √, \pm not ±

POSITIONING REQUIREMENTS (CRITICAL):
- Each element MUST have unique position within screen bounds
- SAFE positions only: .to_edge(UP), .shift(UP*1.5), .shift(DOWN*1.5), .shift(LEFT*2.5), .shift(RIGHT*2.5)
- NO extreme shifts: avoid UP*3, DOWN*3, LEFT*4, RIGHT*4 (goes off-screen)
- NO overlapping: if one element uses .shift(UP*1.5), others must use different positions
- Test positions: Title=top, Main=upper center, Secondary=lower center, Sides=left/right

TEMPLATE TO ADAPT:

        # Title at top
        title = Text("{title}").scale(0.8).to_edge(UP, buff=0.5)
        
        # Axes positioned in lower area
        axes = Axes(
            x_range=[-3, 3, 1],
            y_range=[-2, 4, 1], 
            x_length=6,
            y_length=4,
            axis_config={{"color": BLUE}}
        ).shift(DOWN * 0.5)
        
        # Function plot
        function = axes.plot(lambda x: {function_expr}, color=RED)
        
        # Equation display
        equation = MathTex(r"{equation}").shift(UP * 1.5)
        
        # Animation sequence
        self.play(Write(title))
        self.wait(1)
        self.play(Write(equation))
        self.wait(1)
        self.play(Create(axes))
        self.wait(1)
        self.play(Create(function))
        self.wait(2)
                

Replace placeholders with scene-specific values and ensure working Manim code.

Generate complete Python code:
SMART POSITIONING REQUIREMENTS:
- Analyze the content TYPE first: equation, diagram, comparison, process
- Position based on content meaning, not just arbitrary rules
- Main subject (equation/diagram) should be CENTER or slightly UP
- Supporting text should be BELOW the main subject
- Comparisons should use LEFT/RIGHT positioning
- Sequential content should use TOP-to-BOTTOM flow
- NEVER fade out main content - only temporary highlights

CAREFULLY IMPLEMENT THIS