• 【题解】 [NOI2009]变换序列 (二分图匹配)


    懒得复制,戳我戳我

    Solution:

    • 这个题面出的很毒瘤,读懂了其实是个板子题qwq
    • 题面意思:有个(0)(N-1)的数列是由另一个数列通过加减得到的,相当于将(A_i)变成(i),每一步的代价计算就是(min(A_i-i,N-(A_i-i))),并且(A_ileft(0<=i<N ight))互不相同,读入代价,要求字典序最小的满足要求的数列
    • 我们设读入的为(w[i])
    • 思路其实很简单,(i)只可能是由(i-w[i]) 或者 (i+w[i]) 或者 (i+N-w[i]) 或者 (i-N+w[i]),然后我们把符合范围(0)(N-1)的对应点从大到小建图,这样可以保证搜的时候是从小的点开始
    • 然后就从(N-1)(0)进行二分图匹配,如果无法匹配就输出(No Answer),这样从后到前匈牙利算法去做,保证越前面的匹配的数是最小的。
    • 因为(be[i])中存的是(i)数字对应变成的数字是什么,所以反过来存一下输出就好啦

    主要是想字典序最小的地方有点emmm神奇,其他的地方还是比较显然的


    Code:

    //It is coded by Ning_Mew on 3.17
    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int maxn=1e5+7;
    
    bool vis[maxn];
    int n,w[maxn],be[maxn],ans[maxn];
    int head[maxn],cnt=0;
    struct Edge{
      int nxt,to;
    }edge[maxn*4];
    priority_queue<int>q;
    
    void add(int from,int to){
      edge[++cnt].nxt=head[from];
      edge[cnt].to=to;
      head[from]=cnt;
    }
    bool find(int k){
      for(int i=head[k];i!=0;i=edge[i].nxt){
        int v=edge[i].to;
        if(!vis[v]){
          vis[v]=true;
          if(be[v]==-1||find(be[v])){be[v]=k;return true;}
        }
      }return false;
    }
    int main(){
      scanf("%d",&n);
      while(!q.empty())q.pop();
      for(int i=0;i<n;i++){
        scanf("%d",&w[i]);
        q.push(i-w[i]);  q.push(i+w[i]);
        q.push(i+n-w[i]);q.push(i-n+w[i]);
        while(!q.empty()){
          int box=q.top();q.pop();
          //cout<<box<<endl;
          if(box>=0&&box<n)add(i,box);//cout<<i<<' '<<box<<endl;
        }
      }
      memset(be,-1,sizeof(be));
      for(int i=n-1;i>=0;i--){
        memset(vis,false,sizeof(vis));
        if(find(i));
        else{printf("No Answer
    ");return 0;}
      }
      for(int i=0;i<n;i++)ans[be[i]]=i;
      for(int i=0;i<n;i++)printf("%d ",ans[i]);printf("
    ");
      return 0;
    }
    
    
  • 相关阅读:
    洛谷 P1396 营救(二分答案)
    洛谷 P1807 最长路(toposort)
    洛谷 P1137 旅行计划(toposort)
    [bzoj3032][TYVJ P1924]七夕祭(环形均分纸牌,货仓选址)
    BZOJ3043 IncDec Sequence (差分)
    BZOJ2200 道路与航线(dijk+拓扑排序)
    P1462 通往奥格瑞玛的道路(二分+dijkstra)
    P1020 导弹拦截 O(nlogn)做法
    背包整理(01背包,完全背包,多重背包,分组背包)(待更新)
    [模板]树链剖分
  • 原文地址:https://www.cnblogs.com/Ning-Mew/p/8590580.html
Copyright © 2020-2023  润新知