黑色炫酷灯饰照明科技企业商务网站模板/百度站长工具域名查询
传送门:BZOJ1562-变换序列
由于题目是图片形式,就不贴了。
题解
我们把每个数与可以变换的两个标号之间连一条无向边,跑一下二分图最大匹配就好啦。
注意dfs的顺序和边的排序
代码
#include<bits/stdc++.h>
#define o(x,y) g[x].push_back(y);
using namespace std;
const int N=1e4+10;
int n,x,now,lk[N<<1];
int vis[N<<1],cnt,ans;
vector<int>g[N<<1];inline bool dfs(int x)
{int oi,len=g[x].size();for(int i=0;i<len;i++){oi=g[x][i];if(vis[oi]!=cnt){vis[oi]=cnt;if(lk[oi]==-1){lk[oi]=x;return true;}else if(dfs(lk[oi])){lk[oi]=x;return true;}}}return false;
}inline int maxmatch()
{int num=0;for(int i=n-1;i>=0;i--){cnt++;if(dfs(i)){num++;}}return num;
}int main(){scanf("%d",&n);for(int i=0;i<n;i++){scanf("%d",&x);now=(i+x)%n + n;g[i].push_back(now);g[now].push_back(i);now=(i-x+n)%n + n;g[i].push_back(now);g[now].push_back(i);}for(int i=0;i<(n<<1);i++){sort(g[i].begin(),g[i].end());lk[i]=-1; }ans=maxmatch();if(ans!=n){printf("No Answer\n");}else{for(int i=0;i<n;i++){lk[lk[i+n]]=i;}for(int i=0;i<n;i++){printf("%d",lk[i]);if(i!=n-1){printf(" ");}}}return 0;
}