A
将数据存入数组,根据下标取最小值
B
根据题意,相邻的两个都是朋友,给出朋友关系,构造满足所有关系的排列
假如此时 2 3 1 4 5 满足朋友关系,那么5之后的第一个数字一定是4的朋友,以此递推,就可以得到排列
所以现在的问题在于,如何得到这个最初始的排列?
由于数据较小,我们以1为其他4个数字的朋友,全排列所有的可能,一个一个去检验即可
#include<bits/stdc++.h>using namespace std;const int maxn=1e5+10;
int n;
vector<int >q[maxn];
int nt[5],ans[maxn];
bool book[5],used[maxn];int get(int x,int a,int b,int c){for(int v:q[x]){if(v!=a && v!=b && v!=c) return v;}return -1;
}
bool check(){ans[2]=1;int d[5]={0,1,3,4};for(int i=0;i<4;++i) ans[d[i]]=q[1][nt[i]];//排列输入答案for(int i=5;i<n+5;++i){ans[i]=get(ans[i-2],ans[i-4],ans[i-3],ans[i-1]);//递推后面if(ans[i]==-1) return 0;//出现不可能的构造}for(int i=0;i<5;++i)if(ans[i]!=ans[n+i]) return false;//后5个应该与前5个重叠memset(used,0,sizeof used);for(int i=0;i<n;++i){//判重,出现重复的即有错int t=ans[i];if(used[t]) return 0;used[t]=1;}for(int i=0;i<n;++i) printf("%d ",ans[i]);return 1;
}
bool dfs(int u){//全排列if(u==4) return check();for(int i=0;i<4;++i)if(!book[i]){nt[u]=i;book[i]=1;if(dfs(u+1)) return true;book[i]=0;}return 0;
}
int main(){scanf("%d",&n);for(int i=0;i<n*2;++i){int u,v;scanf("%d %d",&u,&v);q[u].push_back(v);q[v].push_back(u);}if(!dfs(0)) puts("-1");return 0;
}
C
经典模型
并查集染色
对于一个区间[l,r]的奶农都被其中的x打败,所以用ans记录他们被谁打败
而被打败的奶牛,用并查集f[]指向后一头牛,由于路径压缩,那么区间内的每头牛都会指向r+1,这样下次涉及该区间操作时,就会跳过该区间
该题中第x头牛会被保留,所以删除的区间是[l,x-1],[x+1,r]
#include<bits/stdc++.h> using namespace std;const int maxn= 300010;int n,m;
int f[maxn], ans[maxn];int find(int x)
{if(f[x] != x) return f[x] = find(f[x]);return f[x];
}int main()
{scanf("%d%d", &n, &m);for (int i=1; i<=n+1; i++) f[i]=i;while (m--){int l, r, x;scanf("%d%d%d", &l, &r, &x);for(int i=find(l);i<x;i=find(i)){if (i<x){f[i]=i+1;ans[i]=x;}}for(int i=find(x+1);i<=r;i=find(i)){if (i<=r){f[i]=i+1;ans[i]=x;}}}for (int i=1;i<=n;i++) printf("%d ", ans[i]);return 0;
}
类似题疯狂的馒头