### Apache Airflow version

2.5.3

### What happened

When a DAG is removed from a zip in the DAGs directory, but the zip file remains, it is not marked correctly as inactive. It is still visible in the UI, and attempting to open the DAG results in an `DAG "mydag" seems to be missing from DagBag.` error in the UI.

The DAG is removed from the SerializedDag table, resulting in the scheduler repeatedly erroring with `[2023-04-12T12:43:51.165+0000] {scheduler_job.py:1063} ERROR - DAG 'mydag' not found in serialized_dag table`.

I have done some minor investigating and it appears that [this piece of code](https://github.com/apache/airflow/blob/2.5.3/airflow/dag_processing/manager.py#L748-L772) may be the cause.

`dag_filelocs` provides the path to a specific python file within a zip, so `SerializedDagModel.remove_deleted_dags` is able to remove the missing DAG.

However, `self._file_paths` only contains the top-level zip name, so `DagModel.deactivate_deleted_dags` will only deactivate DAGs where the zip they are contained in is deleted, regardless of whether the DAG is still inside the zip.

I can see there are [other methods that handle DAG deactivation](https://github.com/apache/airflow/blob/2.5.3/airflow/models/dag.py#L2945-L2968) and I'm not sure how these all interact but this does seem to cause this specific issue.

### What you think should happen instead

DAGS that are no longer in the DagBag are marked as inactive

### How to reproduce

Running airflow locally with docker-compose:
- Create a zipfile with 2 DAG py files in in ./dags
- Wait for the DAGs to be parsed by the scheduler and appear in the UI
- Overwrite the existing DAG zip, with a new zip containing only 1 of the original DAG py files
- Wait for scheduler loop to parse the new zip
- Attempt to open the removed DAG in the UI, you will see an error



### Operating System

Debian GNU/Linux 11 (bullseye)

### Versions of Apache Airflow Providers

_No response_

### Deployment

Official Apache Airflow Helm Chart

### Deployment details

_No response_

### Anything else

If I replace the docker image in the docker compose with an image built from this Dockerfile:

```
FROM apache/airflow:2.5.3
RUN sed -i '772s/self._file_paths/dag_filelocs/' /home/airflow/.local/lib/python3.7/site-packages/airflow/dag_processing/manager.py
RUN sed -i '3351s/correct_maybe_zipped(dag_model.fileloc)/dag_model.fileloc/' /home/airflow/.local/lib/python3.7/site-packages/airflow/models/dag.py
```

The DAG is deactivated as expected

### Are you willing to submit PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

timing out / failing, so that new DagRuns can be created.
    :param sla_miss_callback: specify a function or list of functions to call when reporting SLA
        timeouts. See :ref:`sla_miss_callback<concepts:sla_miss_callback>` for
        more information about the function signature and parameters that are
        passed to the callback.
    :param default_view: Specify DAG default view (grid, graph, duration,
                                                   gantt, landing_times), default grid
    :param orientation: Specify DAG orientation in graph view (LR, TB, RL, BT), default LR
    :param catchup: Perform scheduler catchup (or only run latest)? Defaults to True
    :param on_failure_callback: A function or list of functions to be called when a DagRun of this dag fails.
        A context dictionary is passed as a single parameter to this function.
    :param on_success_callback: Much like the ``on_failure_callback`` except
        that it is executed when the dag succeeds.
    :param access_control: Specify optional DAG-level actions, e.g.,
        "{'role1': {'can_read'}, 'role2': {'can_read', 'can_edit', 'can_delete'}}"
    :param is_paused_upon_creation: Specifies if the dag is paused when created for the first time.
        If the dag exists already, this flag will be ignored. If this optional parameter
        is not specified, the global config setting will be used.
    :param jinja_environment_kwargs: additional configuration options to be passed to Jinja
        ``Environment`` for template rendering
        **Example**: to avoid Jinja from removing a trailing newline from template strings ::
            DAG(dag_id='my-dag',
                jinja_environment_kwargs={
                    'keep_trailing_newline': True,
                    # some other jinja2 Environment options here
                }
            )
        **See**: `Jinja Environment documentation
        <https://jinja.palletsprojects.com/en/2.11.x/api/#jinja2.Environment>`_
    :param render_template_as_native_obj: If True, uses a Jinja ``NativeEnvironment``