bzoj1562: [NOI2009]变换序列
匈牙利匹配。
在邻接表中每条边以终点升序排序。从x最后一个点往前进行增广,这样每个点首先都能匹配到字典序最小的位置,如果前面的点找不到匹配点时,后面的点就匹配到稍大一点的y匹配点上。
建图说明:每个点有且只会有俩个点符合距离的要求,可以想想为什么。
y点要+n与x点区分开来。
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> using namespace std; const int maxn = 30000 + 10; vector<int> g[maxn]; bool vis[maxn]; int p[maxn]; int n; bool find(int u) { if(vis[u]) return false; vis[u]=true; for(int i=0,v;i<g[u].size();i++) { v=g[u][i]; if(!p[v] || find(p[v])) { p[v]=u; p[u]=v; return true; } } return false; } int main() { scanf("%d",&n); for(int i=0,d;i<n;i++){ scanf("%d",&d); int a=(i+d)%n,b=(i+n-d)%n; if(a>b) swap(a,b); g[i].push_back(a+n); g[i].push_back(b+n); } for(int i=n-1;i>=0;i--) { memset(vis,0,sizeof(vis)); if(!find(i)) { printf("No Answer"); return 0; } } for(int i=0;i<n;i++) if(i) printf(" %d",p[i]-n); else printf("%d",p[i]-n); return 0; }