【洛谷P1963】變換序列
阿新 • • 發佈:2019-04-27
求一個 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】變換序列