讀懂題意後發現這道題最主要是要求出字典序最小的排列,考察了匈牙利演算法的實質。
首先對於$d_i$的定義,我們可以解出可能的$t_i$,然後將$i$與$t_i$連邊,求最大匹配。
如果最大匹配$但是要求字典序最小。
第一中方法在我$ac$後翻看題解而寫的。
這個程式是根據匈牙利演算法的實質寫的。
對於乙個待匹配點,如果從其中一條非匹配邊能匹配上,則這條匹配邊一定會被匹配上。
我們將所有$i$連向$t_i$的邊從小到大排序,從最後乙個點開始匹配,從小的$t_i$到大的$t_i$判斷。最後答案一定是字典序最小的。
為什麼呢?根據剛剛的總結,也就是能保證第$1$個點一定能選擇最好的匹配,因為非匹配邊從最好的往最壞的情況列舉,匹配上的一定就是最好的,因為假如前面沒有匹配上,原因就在於選擇前面的邊一定不能匹配。
1 #include 23using
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 23using
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 簡要題意就是給定乙個排列,每個元素有兩個對應關係,問你是否能將該排列轉換為另乙個排列,並使之字典序最小,如果不考慮字典序的話,這題就是裸的一道求二分圖完美匹配的題,那麼我們該如何考慮字典序呢?我們可以按字典序暴力列舉左邊的點與右邊的哪個點相匹配,再跑二分圖。實際上我們可以不這樣做,二分圖匹...