magic ——4124
思路:强模拟,不解释…
message ——4125
思路:仔细读完题,实际上是找一个最小的环,那么便bfs,但这样只有60,
因为n<=200 000,也便知道只有O(n log n)的复杂度,而且,此题的关系比较明显——父子关系,脑海一闪而过——并查集,再思考一下,并两个集合,查一数,十分符合。
#include<bits/stdc++.h>
#define REP(i,f,t ) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t ) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 200005
using namespace std;
int n;
vector<int>E[N];
bool vis[N];
struct p100{
int ans;
int D[N],fa[N],nxt[N];
int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
void merege(int x,int y){
int fx=Find(x);
int fy=Find(y);
fa[fx]=fy;
}
void dfs(int x,int dep){
vis[x]=1;
D[x]=dep;
if(!vis[nxt[x]])dfs(nxt[x],dep+1);
else {
int sum=D[x]-D[nxt[x]]+1;
ans=min(ans,sum);
}
}
void solve(){
ans=INF;
REP(i,1,n)fa[i]=i;
REP(i,1,n){
int x;scanf("%d",&x);nxt[i]=x;
if(Find(x)!=Find(i))merege(i,x);
else {
memset(vis,0,sizeof(vis));
dfs(i,0);
}
}
cout<<ans<<endl;
}
}p100;
int main(){
// freopen("message.in","r",stdin);
// freopen("message.out","w",stdout);
cin>>n;
p100.solve();
}
landlords ——4126
思路:爆搜…(还是要考虑周到,再敲代码),也就这么几种特殊情况:单顺子,双顺子,三顺子,三带一或二,四不带,四带二单或一对。而这看起来挺多,但再次分类一下,单顺,双顺,三顺,三带,四带。
#include<bits/stdc++.h>
#define REP(i,f,t ) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t ) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 30
using namespace std;
int T,n,x,y,ans;
int mark[N];
void Init(){
memset(mark,0,sizeof(mark));
ans=0;
}
bool check(){
REP(i,1,15)
if (mark[i]) return 0;
return 1;
}
void dfs(int cnt){
if(cnt>ans)return;
if (check()) {
ans=min(ans,cnt);
return;
}
int sum=0;
REP(i,1,13)if(mark[i])sum++;
if(mark[14]+mark[15])sum++;
ans=min(ans,cnt+sum);
REP(l,1,5){
if (l==1){// single shunzi
REP(i,1,8)
if (mark[i]) {
bool flag=1;
for (int j=i+1; j<=i+3; ++j)
if (!mark[j]) {
flag=0;
break;
}
if (!flag) continue;
for (int j=i+4; j<13&&mark[j]; ++j) {
for (int k=i; k<=j; ++k) --mark[k];
dfs(cnt+1);
for (int k=i; k<=j; ++k) ++mark[k];
}
}
}
if (l==2) {//double shunzi
REP(i,1,10)
if (mark[i]>=2&&mark[i+1]>=2)
for (int j=i+2; j<13&&mark[j]>=2; ++j) {
for (int k=i; k<=j; ++k) mark[k]-=2;
dfs(cnt+1);
for (int k=i; k<=j; ++k) mark[k]+=2;
}
}
if (l==3) {//triple shunzi
REP(i,1,11)
if (mark[i]>=3) {
if (mark[i+1]<3) continue;
for (int j=i; j<13&&mark[j]>=3; ++j) {
for (int k=i; k<=j; ++k) mark[k]-=3;
dfs(cnt+1);
for (int k=i; k<=j; ++k) mark[k]+=3;
}
}
}
if (l==4) {//san dai
REP(i,1,13)
if (mark[i]>=3) {
mark[i]-=3;
REP(j,1,15)
if (mark[j]) {
--mark[j];
dfs(cnt+1);
++mark[j];
}
REP(j,1,15)
if (mark[j]>=2) {
mark[j]-=2;
dfs(cnt+1);
mark[j]+=2;
}
mark[i]+=3;
}
}
if (l==5) {//si dai
REP(i,1,15)
if (mark[i]>=4) {
mark[i]-=4;
REP(j,1,15)
if (mark[j]) {
--mark[j];
REP(k,j,15)
if (mark[k]) {
--mark[k];
dfs(cnt+1);
++mark[k];
}
++mark[j];
}
mark[i]+=4;
}
REP(i,1,15)
if (mark[i]>=4) {
mark[i]-=4;
REP(j,1,15)
if (mark[j]>=2) {
mark[j]-=2;
REP(k,j,15)
if (mark[k]>=2) {
mark[k]-=2;
dfs(cnt+1);
mark[k]+=2;
}
mark[j]+=2;
}
mark[i]+=4;
}
}
}
}
int main() {
scanf("%d%d",&T,&n);
while (T--){
Init();
REP(i,1,n){
scanf("%d%d",&x,&y);
if (!x) mark[y+13]++;
if (x==1||x==2) mark[x+11]++;
if (x>=3) mark[x-2]++;
}
REP(i,1,13)if(mark[i])ans++;
if(mark[14]+mark[15])ans++;
dfs(0);
printf("%d\n",ans);
}
}
小结:今天的最后一题还是敲地太乱了,没怎么想好久开始敲,结果连爆搜都敲不出来——深思熟虑后再动键盘…