理解hash过程
首先可知,先放进去肯定是h[i]%n==i的位置,这些个位置放进set按照字典序顺序来,然后每安排一个这样点,对于它后一位的值,如果还没被放入set,则如果它%对应的位置已经放入set了则它放入set ~
ac代码:
#include <bits/stdc++.h> using namespace std; #define per(i,a,b) for(int i=a;i<b;i++) #define MP make_pair typedef pair<int,int> PII; typedef vector<int> VI; const int inf =0x3f3f3f; #define siz 200005 int n,h[siz],f[siz];//f[i]表示i位置现在要考虑的点位置 bool vis[siz]; void init() { memset(vis,false,sizeof(vis)); per(i,1,n)f[i]=i; } int Find(int u){return f[u]==u?u:f[u]=Find(f[u]);} int main() { int T; scanf("%d",&T); while(T--){ scanf("%d",&n); init(); set<PII>st;//带排序功能嘛 per(i,0,n){scanf("%d",&h[i]);if(h[i]==-1)vis[i]=true;} per(i,0,n)f[i]=i; per(i,0,n){ if(vis[i])continue; if(h[i]%n == i){st.insert(MP(h[i],i));vis[i]=true;} } VI ans; while(!st.empty()){ auto tmp=*st.begin(); st.erase(st.begin()); ans.push_back(tmp.first); assert(Find(tmp.second)==tmp.second);//表示这个点上一步刚处理 f[tmp.second]=Find((tmp.second+1)%n); if(f[tmp.second]!=tmp.second){ int to=f[tmp.second]; if(vis[to]==false&&Find(h[to]%n)==to){ vis[to]=true; st.insert(MP(h[to],to)); } } } bool flag=true; per(i,0,n)if(vis[i]==false){flag=false;break;} if(!flag)puts("-1"); else { if(ans.empty())puts(""); else{ per(i,0,(int)ans.size())printf("%d%c",ans[i]," \n"[i==(int)ans.size()-1]); } } } return 0; }
原文地址:https://www.cnblogs.com/WindFreedom/p/9385303.html
时间: 2024-11-05 06:28:08