zoukankan      html  css  js  c++  java
  • [NOI2009]变换序列

    题意

    Here

    思考

    简要题意就是给定一个排列,每个元素有两个对应关系,问你是否能将该排列转换为另一个排列,并使之字典序最小,如果不考虑字典序的话,这题就是裸的一道求二分图完美匹配的题,那么我们该如何考虑字典序呢?

    我们可以按字典序暴力枚举左边的点与右边的哪个点相匹配,再跑二分图。

    实际上我们可以不这样做,二分图匹配的过程实际上是贪心的过程,我们为了满足当前点,有时会让已经匹配的点更换匹配点,那么我们让字典序小的靠前选择,并且下往上倒着匹配,就可以满足字典序最小了。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int M = 100010;
    const int N = 100010;
    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*10+ch-'0';ch=getchar();}
    	return x * f;
    }
    struct node{
    	int nxt, to;
    }edge[M << 1];
    int head[N], num;
    void build(int from, int to){
    	edge[++num].nxt = head[from];
    	edge[num].to = to;
    	head[from] = num;
    }
    int match[N], vis[N];
    int n;
    int ANS[N];
    bool dfs(int u){
    	for(int i=head[u]; i; i=edge[i].nxt){
    		int v = edge[i].to;
    		if(!vis[v]){
                vis[v] = 1;
                if(match[v] == -1 || dfs(match[v])){
                    match[v] = u; ANS[u] = v; return 1;
                }
    		}
    	}
    	return 0;
    }
    int main(){
    	n = read();
    	for(int i=0; i<=2*n+1; i++) match[i] = -1;
    	for(int i=0; i<=n-1; i++){
    		int d = read();
    		int a = (i + d) % n + n, b = (i - d + n) % n + n;
    		if(a < b) swap(a, b);
    		build(i, a);
    		build(i, b);
    	}
    	int ans = 0;
    	for(int i=n-1; i>=0; i--){
    		memset(vis, 0, sizeof(vis));
    		if(!dfs(i)){
    			puts("No Answer");
    			return 0;
    		}
    	}
    	for(int i=0; i<=n-1; i++){
    		cout<<ANS[i] - n<<" ";
    	}
    	return 0;
    }
    
    

    总结

    有几点要注意的:

    1. 点是从零开始编号的,所以 (match) 数组初始化为 (-1) 而不是 (0)
    2. 有一个小技巧,对每个点 (u) 进行匹配的时候,不用重新清零 (vis[]) 数组,只用在标记时将其标记为当前匹配点的编号( (u) )就好~
  • 相关阅读:
    BadUSB 利用
    java 将函数作为参数传递
    odoo12 修行提升篇之 常用的高阶函数 (二)
    odoo12 修行提升篇之 异步定时任务 (一)
    odoo12 修行基础篇之 利用kanban做分析 点击跳转分析模型列表 (九)
    odoo12 修行基础篇之 kanban (八)
    odoo12 修行基础篇之 记录批处理 (七)
    odoo12 修行基础篇之 列表的筛选和分组 (六)
    odoo12 修行基础篇之 添加记录编码 (五)
    odoo12 修行基础篇之 添加工作流和操作记录 (四)
  • 原文地址:https://www.cnblogs.com/alecli/p/9915125.html
Copyright © 2011-2022 走看看