配列を「都市名」と「数」で2つ宣言しているのは冗長
「数」についてはそうですね。またそれぞれを配列として宣言するより構造体としてまとめた方がよいという観点もあります。しかし元のコードでは「都市名」については、冗長云々より先に正しくない実装になっていますのでその点をコメントします。
もし配列の要素数Nが固定(定数)なら
C
1#define N 10
2
3int min[N];
4
5int main() {
6 for (int i = 0; i < N; i++) {
7 min[i] = ...; // 配列の要素のアクセス
8 }
9}
のように書けます。固定サイズの配列はどのバージョンのCでも書けますので基本的な書き方と言えるでしょう。
しかし配列の要素数Nが可変(プログラムを実行する度に値が違うものとなり得る)なら、基本は「mallocにより動的にメモリーを確保する」方法をまず学ぶことをお勧めします。それを意識しているかどうかはっきりしませんが、VLA(variable length array)を使っておられます。しかしコードの完成度からいって自分は質問者さんにまずmallocを使う方法を学ぶことをお勧めします。Nが可変のとき配列を動的に確保するにはCではポインターを使って次のように書きます。
C
1#include <malloc.h>
2...
3int N;
4scanf("%d", &N); // プログラムを実行する度にNは変わる。つまりNは定数ではなく変数
5int *min = (int*)malloc(sizeof(int) * N); // mallocで任意の大きさの領域を確保
6for (int i = 0; i < N; i++) {
7 min[i] = ...; // ポインターminを使ってもあたかも配列のように要素をアクセスできます
8}
文字列は例えば"abc"であれば最小限、3文字+末尾のNUL文字の合計4個のchar要素を格納できる領域が必要です。また"abc","def"という2つの文字列を格納するには少なくとも4個のchar要素の領域が2セット必要です。しかしあなたのコード上では単に文字列の個数Nに対して要素数をN+1にしています。Nは文字列の個数であって長さではありませんしそもそも長さ×個数の領域が必要という点を配慮できていません。
長さがLの文字列をN個分格納するためには最小でも(L+1)xN個のchar要素が必要です。このような領域は2次元配列として表現したりポインターのポインターとして宣言したりといくつかのバリエーションがありますが、そのような領域を配列やポインターでどう書くべきかは、ある程度の学習が必要です。ここでは詳細は述べず例のみ挙げてみます。(いくつかの箇所ではintでなくsize_tを使うほうがよりよいコードと言えるかも知れませんが以下の例ではintとしています。)
文字列の最大長も文字列の個数も固定とし2次元配列にする場合
c
1#define MAXL 20
2#define N 10
3char town_names[N][MAXL + 1];
文字列の最大長は固定、文字列の個数は可変の場合
c
1#include <stdio.h>
2#include <malloc.h>
3
4#define MAXL 20
5
6typedef char TOWN_NAME[MAXL + 1];
7
8int main() {
9 int N;
10 TOWN_NAME *town_names;
11
12 scanf("%d", &N);
13 town_names = (TOWN_NAME*)malloc(sizeof(TOWN_NAME) * N);
14 for (int i = 0; i < N; i++) {
15 scanf("%s", town_names[i]);
16 }
17 ...
18}
文字列の最大長も文字列の個数も可変としたい場合
c
1#include <stdio.h>
2#include <malloc.h>
3#include <string.h>
4
5// 個々の文字列の長さは可変とするがこの例では読み込みの際のバッファー長は固定としておく
6#define MAXL 20
7
8int main() {
9 int N;
10 char **town_names;
11 char buffer[MAXL + 1];
12
13 scanf("%d", &N);
14 town_names = (char**)malloc(sizeof(char*) * N);
15
16 for (int i = 0; i < N; i++) {
17 scanf("%s", buffer);
18 int town_name_len = strlen(buffer);
19 town_names[i] = (char*)malloc(town_name_len + 1);
20 strcpy(town_names[i], buffer);
21 }
22 ...
23}
なお、C言語の仕様は時代の変遷によって変化しているので「ずっと昔から使える機能」と「現在でも一部のコンパイラーでしか使えない機能」が入り混じっています。こうしたことは他の言語でも同様なので回答の際には「何を前提にするか」が回答者の知識や主観に左右されることがあります。自分はVLAをこのサイトで教えていただくまで知らなかった(w;)のですが、知った後でも「多くのCコンパイラーでは使えるとしても基本としてまず知っておくべきことは何か」との観点からVLAでなくmallocを使う方法を述べ、「新しい仕様ではあるが推奨したい書き方」という考えからc99以上で利用できる「変数をブロックの先頭で宣言しなくても使う場所で宣言できる」仕様を前提に回答しています。(それ以外に自分でも気づかない前提を置いている箇所があるかも知れません。)