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) - Scene title
        # 2. Diagram: Group of Circles, Lines, Arrows, Text (weights) - .shift(LEFT * 2.5) - Visual focus on weighted graph
        # 3. Secondary Text: Text - .shift(DOWN * 1.5) - Explanation / introduction text
        # 4. Main Equation: MathTex - .shift(UP * 1.5) - Key formula / concept (Dijkstra's algorithm description)

        # Create Title
        title = Text("Understanding the Shortest Path Problem").to_edge(UP, buff=0.5).set_color(WHITE)

        # Create weighted graph diagram on left side
        # Nodes as Circles with labels
        nodes = VGroup()
        node_positions = {
            "A": LEFT * 2 + UP * 0.5,
            "B": LEFT * 1 + UP * 1.5,
            "C": LEFT * 1 + DOWN * 0.5,
            "D": LEFT * 0 + UP * 0.5,
        }
        node_circles = {}
        node_labels = {}
        for name, pos in node_positions.items():
            circ = Circle(radius=0.3, color=BLUE)
            circ.move_to(pos)
            label = Text(name, color=WHITE).move_to(pos)
            nodes.add(circ, label)
            node_circles[name] = circ
            node_labels[name] = label

        # Edges as Lines with weights (Text)
        edges = VGroup()
        edge_data = [
            ("A", "B", 4),
            ("A", "C", 1),
            ("C", "B", 2),
            ("B", "D", 1),
            ("C", "D", 5),
        ]
        edge_lines = []
        edge_weights = []
        for start, end, w in edge_data:
            line = Line(node_positions[start], node_positions[end], color=WHITE)
            # Place weight text at midpoint shifted slightly perpendicular
            midpoint = (node_positions[start] + node_positions[end]) / 2
            # Calculate perpendicular offset
            vec = node_positions[end] - node_positions[start]
            perp = np.array([-vec[1], vec[0], 0])
            perp = perp / np.linalg.norm(perp) * 0.3
            weight_text = Text(str(w), color=YELLOW).scale(0.6).move_to(midpoint + perp)
            edges.add(line, weight_text)
            edge_lines.append(line)
            edge_weights.append(weight_text)

        graph_group = VGroup(nodes, edges).shift(LEFT * 2.5)

        # Secondary text at bottom center - introduction to shortest path problem
        intro_text = Text(
            "Shortest path problem:\nFind the minimum distance from a start node to all others.",
            color=WHITE,
            line_spacing=1.2,
        ).shift(DOWN * 1.5)

        # Main equation (concept) at upper center
        main_eq = MathTex(
            r"\text{Dijkstra's Algorithm: }",
            r"\text{Find shortest paths from a start node}",
            r"\text{in a graph with non-negative edge weights}",
            font_size=28,
        ).shift(UP * 1.5).set_color(GREEN)

        # Animation Sequence:

        # 1. Show title and graph with intro text
        self.play(Write(title), Create(graph_group), Write(intro_text), run_time=3)
        self.wait(1)

        # Fade out intro text and graph, keep title
        self.play(FadeOut(intro_text), FadeOut(graph_group), run_time=1)
        self.wait(0.5)

        # 2. Show main equation (concept)
        self.play(Write(main_eq), run_time=2)
        self.wait(1)

        # 3. Show graph again on left side with title and main equation visible
        self.play(Create(graph_group), run_time=2)
        self.wait(1)

        # 4. Show secondary text at bottom explaining edge weights and cumulative distance
        secondary_text = Text(
            "Edge weights represent distances.\n"
            "Dijkstra's algorithm accumulates these distances to find shortest paths.",
            color=WHITE,
            line_spacing=1.2,
        ).shift(DOWN * 1.5)

        self.play(Write(secondary_text), run_time=2)
        self.wait(2)

        # Cleanup: fade out secondary text and graph, keep title and main equation
        self.play(FadeOut(secondary_text), FadeOut(graph_group), run_time=1)
        self.wait(0.5)

        # 5. Transition text at bottom center
        transition_text = Text(
            "Now that we understand the problem,\nlet’s explore how Dijkstra’s algorithm works step-by-step.",
            color=WHITE,
            line_spacing=1.2,
        ).shift(DOWN * 1.5)

        self.play(Write(transition_text), run_time=2)
        self.wait(2)

        # Final cleanup: fade out transition text, keep title and main equation visible
        self.play(FadeOut(transition_text), run_time=1)
        self.wait(1)
```
---

### Explanation of the plan:

**Layout:**

- Title at top edge: `title.to_edge(UP, buff=0.5)`
- Main equation (concept) near upper center: `.shift(UP * 1.5)`
- Weighted graph diagram on left side: `.shift(LEFT * 2.5)`
- Secondary / intro / transition text at lower center: `.shift(DOWN * 1.5)`

**Elements:**

1. Title (Text)
2. Weighted graph (Circles, Lines, Text weights)
3. Intro / secondary / transition texts (Text)
4. Main equation (MathTex)

**Animations:**

- Start with title + graph + intro text
- Fade out graph and intro text, keep title
- Show main equation
- Show graph again
- Show secondary explanation text
- Fade out secondary text and graph
- Show transition text
- Fade out transition text

**Cleanup:**

- Fade out highlights (graph edges and weights) when done
- Fade out old descriptions before new ones
- Keep main equation visible after it appears
- Clear temporary elements (intro, secondary, transition texts) between sections

**Colors:**

- BLUE for nodes
- WHITE for text and edges
- YELLOW for edge weights
- GREEN for main equation
- Title in WHITE

**Positioning rules strictly followed.**

---

This plan meets all the strict requirements 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