NOI2009 變換序列

2022-03-25 18:50:54 字數 2814 閱讀 1136

讀懂題意後發現這道題最主要是要求出字典序最小的排列,考察了匈牙利演算法的實質。

首先對於$d_i$的定義,我們可以解出可能的$t_i$,然後將$i$與$t_i$連邊,求最大匹配。

如果最大匹配$但是要求字典序最小

第一中方法在我$ac$後翻看題解而寫的。

這個程式是根據匈牙利演算法的實質寫的。

對於乙個待匹配點,如果從其中一條非匹配邊能匹配上,則這條匹配邊一定會被匹配上

我們將所有$i$連向$t_i$的邊從小到大排序,從最後乙個點開始匹配,從小的$t_i$到大的$t_i$判斷。最後答案一定是字典序最小的。

為什麼呢?根據剛剛的總結,也就是能保證第$1$個點一定能選擇最好的匹配,因為非匹配邊從最好的往最壞的情況列舉,匹配上的一定就是最好的,因為假如前面沒有匹配上,原因就在於選擇前面的邊一定不能匹配。

1 #include 2

3using

namespace

std;45

#define re register

6#define rep(i, a, b) for (re int i = a; i <= b; ++i)

7#define repd(i, a, b) for (re int i = a; i >= b; --i)

8#define maxx(a, b) a = max(a, b);

9#define minn(a, b) a = min(a, b);

10#define ll long long

11#define inf (1 << 30)

1213 inline int

read()

1920

const

int maxn = 1e4 + 5;21

22int n, d[maxn], e[maxn][5

], s[maxn], t[maxn];

2324

intlk[maxn], pt[maxn], vis[maxn];

2526

bool find(int u, int

tag) 36}

37}38return

false;39

}4041int

main()

5253 memset(vis, -1, sizeof

(vis));

54 memset(lk, -1, sizeof

(lk));

55 repd(i, n-1, 0)56

if (!find(i, i))

6061 rep(i, 0, n-1

)62 printf("

%d "

, pt[i]);

6364

return0;

65 }

第二種方法是我自己想到的,比上面的**複雜。

首先有一點:由非匹配邊和匹配邊交替構成的迴路(斷句)翻轉所有邊的匹配與否(斷句)得到的是另一種匹配。

所以我們先找出乙個最大匹配,再通過上面的結論從第乙個點調整使得解更優。最後同樣也能得到字典序最小的匹配。

1 #include 2

3using

namespace

std;45

#define re register

6#define rep(i, a, b) for (re int i = a; i <= b; ++i)

7#define repd(i, a, b) for (re int i = a; i >= b; --i)

8#define maxx(a, b) a = max(a, b);

9#define minn(a, b) a = min(a, b);

10#define ll long long

11#define inf (1 << 30)

1213 inline int

read()

1920

const

int maxn = 1e4 + 5;21

22int n, d[maxn], e[maxn][5

], s[maxn], t[maxn];

2324

intlk[maxn], pt[maxn], vis[maxn];

2526

bool find(int u, int

tag) 36}

37}38return

false;39

}4041bool dfs(int u, int

rt)

49if (vis[v] !=rt) 56}

57}58return

false;59

}6061int

main()

7273 memset(vis, -1, sizeof

(vis));

74 memset(lk, -1, sizeof

(lk));

75 rep(i, 0, n-1)76

if (!find(i, i))

8081 memset(vis, -1, sizeof

(vis));

82 rep(i, 0, n-1)83

dfs(i, i);

8485 rep(i, 0, n-1

)86 printf("

%d "

, pt[i]);

8788

return0;

89 }

noi2009變換序列

2009年noi全國競賽 時間限制 1 s 空間限制 128000 kb 題目等級 大師 master 題解 description 對於n個整數0,1,n 1,乙個變換序列t可以將i變成ti,其中 ti 且ui 1 to n 1 任意x,y 定義x和y之間的距離d x,y min。給定每個i和ti...

NOI2009 變換序列

51 1 2 2 1 1 2 4 0 3 30 的資料中n 50 60 的資料中n 500 100 的資料中n 10000。二分圖匹配 匈牙利演算法的原理是衝突時替換 不過要求字典序最小,乙個點會連出2條邊,加邊先加入大的,這樣在匹配時就會先匹配小的 不過這是針對於鏈式前向星 然後如果i和j都匹配了...

NOI2009 變換序列

here 簡要題意就是給定乙個排列,每個元素有兩個對應關係,問你是否能將該排列轉換為另乙個排列,並使之字典序最小,如果不考慮字典序的話,這題就是裸的一道求二分圖完美匹配的題,那麼我們該如何考慮字典序呢?我們可以按字典序暴力列舉左邊的點與右邊的哪個點相匹配,再跑二分圖。實際上我們可以不這樣做,二分圖匹...