1. 程式人生 > >【洛谷P1963】變換序列

【洛谷P1963】變換序列

求一個 swe const ems 由於 一個 tor put vector

題目大意:對於一個順序序列,求一個合法置換,可以滿足一些約束,若存在多個合法置換,則輸出字典序最小的一個置換。

題解:對於序列的置換是否有解的問題,可以和二分圖的完美匹配相關聯。由於是字典序最小,顯然需要貪心考慮。在匈牙利算法執行的過程中,對於每個點來說,可以優先匹配符合條件的最小的點;對於左邊點集來說,可以從後往前進行匹配,這樣可以保證字典序小的點更可能搶到字典序小的點。

代碼如下

#include <bits/stdc++.h>
#define pb push_back
#define all(x) x.begin(),x.end()
using namespace std;
const int maxn=1e4+10;

vector<int> G[maxn];
int n,match[maxn],t[maxn];
bool vis[maxn];

void read_and_parse(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        int d;scanf("%d",&d);
        int x=(i-d+n)%n,y=(i+d)%n;
        G[i].pb(x),G[i].pb(y);
    }
    for(int i=0;i<n;i++)sort(all(G[i]));
}

bool dfs(int u){
    for(auto v:G[u])if(!vis[v]){
        vis[v]=1;
        if(!match[v]||dfs(match[v])){
            match[v]=u;return 1;
        }
    }
    return 0;
}

void solve(){
    int ret=0;
    for(int i=n-1;i>=0;i--){
        memset(vis,0,sizeof(vis));
        if(dfs(i))++ret;
    }
    if(ret<n)return (void)puts("No Answer");
    for(int i=0;i<n;i++)t[match[i]]=i;
    for(int i=0;i<n;i++)printf("%d ",t[i]);
    puts("");
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

【洛谷P1963】變換序列