P1963 [NOI2009] 变换序列

P1963 [NOI2009] 变换序列
求最小字典序
匈牙利算法进行匹配
因为每一次是要求已经匹配好的人进行换对象
如果从前面开始,那就是会要求前面已经匹配好的人换对象,答案就不一定是字符串最小
而如果从后面开始,那就是要求后面已经匹配好的人换对象,一定可以保证局部字典序最小

//选择字典序最小的就可以了
//最多和两个点进行匹配
#include <bits/stdc++.h>
using namespace std;
const int N=10005;
const int M=2*N;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*f;
}

int g[N][2];
int vis[N],match[N];
int ans[N];

bool dfs(int now,int dep) {
    for(int i=0;i<2;i++) {
        int to=g[now][i];
        if(vis[to]==dep)continue;
        vis[to]=dep;
        if(match[to]==-1||dfs(match[to],dep)) {
            match[to]=now;
            ans[now]=to;
            return 1;
        }
    }
    return 0;
}

int main() {
    memset(match,-1,sizeof(match));
    memset(vis,-1,sizeof(vis));
    int n=read();
    for(int i=0;i<n;i++) {
        int x=read();
        int t1=(i+x)%n,t2=(i-x+n)%n;
        if(t1>t2)swap(t1,t2);
        g[i][0]=t1;
        g[i][1]=t2;
    }
    for(int i=n-1;i>=0;i--)
        if(dfs(i,i)==0)return cout<<"No Answer",0;
    for(int i=0;i<n;i++)cout<<ans[i]<<' ';
    return 0;
}
//逆向思维进行贪心就可以了
//从后面开始就是对的
//有的时候求字典序最小或者说其他东西最小,往往只需要把某些东西调换一下子就可以了
posted @ 2022-12-02 17:13  basicecho  阅读(22)  评论(0)    收藏  举报