P5659 树上的数

Aimee

很恶心的一道题

我们在考场上会遇到很多题,无论多难,都要大声喊出:"无所谓"。

怎么无所谓,有所谓
--scz

10分做法

爆搜

#include<iostream>
#include<cstdio> 
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int t;
int head[2001];
int zn[2001];
int tem[2001];
struct ed{
    int f;
    int to;
    int ne;
    int v;
} e[2001];
int p;
int vis[2001];
int ans[2001],now[2001];
int x,y,z;
void add(int f,int to){
    p++;
    e[p].f=f;
    e[p].ne=head[f];
    e[p].to=to;
    return ;
}
void simex(){
    for(int i=1;i<=n;++i){
        ans[i]=tem[i];
    }
}
void work(){
    for(int i=1;i<=n;++i){
        tem[zn[i]]=i;
    }
    for(int i=1;i<=n;++i){
        now[i]=tem[i]; 
    }
    int f=0;
    for(int i=1;i<=n;++i){
        if(now[i]<ans[i]){
            f=1;
            simex();
            break;
        }else{
            if(now[i]==ans[i])
            continue;
            break;
        }
    }
    return ;
}
void dfs(int now){
    if(now==n-1){
        work();
        return ;
    }
    for(int i=1;i<n;++i){
        if(!vis[i]){
            swap(zn[e[i].f],zn[e[i].to]);
            vis[i]=now+1;
            dfs(now+1);
            vis[i]=0;
            swap(zn[e[i].f],zn[e[i].to]);
        }
    }
    return ;
}
int main(){
    scanf("%d",&t);
    while(t--){
        p=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&x);
            zn[x]=i;
            head[i]=0;
            ans[i]=0x7ffffff;
        }
        for(int i=1;i<n;++i){
            scanf("%d%d",&x,&y);
            add(x,y);
        }
        dfs(0);
        for(int i=1;i<=n;++i){
            cout<<ans[i]<<" ";
        }
        cout<<endl;
    }
    return 0;
}

我高考物理满分
---scz

菊花图

      一个更绕的贪心
      #include<iostream>
#include<cstdio> 
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int t;
int head[2001];
int zn[2001];
int tem[2001];
struct ed{
    int f;
    int to;
    int ne;
    int v;
} e[2001];
int p;
int vis[2001];
int ans[2001],now[2001];
int du[2001];
int fa[2001]; 
int x,y,z;
int Aimee;
int put[2001];
void add(int f,int to){
    p++;
    e[p].f=f;
    du[x]++;
    du[to]++;
    Aimee=max(Aimee,max(du[x],du[to]));
    e[p].ne=head[f];
    e[p].to=to;
    return ;
}
void simex(){
    for(int i=1;i<=n;++i){
        ans[i]=tem[i];
    }
}
int find(int x){
    return x==fa[x]? x:fa[x]=find(fa[x]);
}
void work(){
    for(int i=1;i<=n;++i){
        tem[zn[i]]=i;
    }
    for(int i=1;i<=n;++i){
        now[i]=tem[i]; 
    }
    int f=0;
    for(int i=1;i<=n;++i){
        if(now[i]<ans[i]){
            f=1;
            simex();
            break;
        }else{
            if(now[i]==ans[i])
            continue;
            break;
        }
    }
    return ;
}
void dfs(int now){
    if(now==n-1){
        work();
        return ;
    }
    for(int i=1;i<n;++i){
        if(!vis[i]){
            swap(zn[e[i].f],zn[e[i].to]);
            vis[i]=now+1;
            dfs(now+1);
            vis[i]=0;
            swap(zn[e[i].f],zn[e[i].to]);
        }
    }
    return ;
}
void com(int x,int y){
    fa[fa[find(x)]]=fa[find(y)];
    return ;
} 
//花啊 
void flower(){
    for(int i=1;i<=n;++i){
        fa[i]=i;
        now[zn[i]]=i;
        //now 意味着该数字所处的位置 
        vis[i]=0;
    }
    for(int i=1;i<n;++i){
        cout<<"i"<<i<<endl;
        for(int j=1;j<=n;++j){
            if(!vis[j]&&find(now[i])!=find(j)){
                vis[j]=1;
                put[now[i]]=j;
                //那么,就应该把这个数字扔到j上去
                //也就是put i的位置到j
                //但是,因为这是个菊花图
                //你把A扔到了B,那么B是不可能再回到A的
                //因为是菊花图,用一个并查集解决
                //就正如样例中的图
                //1肯定不能留在1,那么最好的办法是把1送到2好点上,也是就put[now[1]]=2;
                //那么这么搞 i号点的位置就会被放个 j
                //交换了
                 //同一个并查集是不能乱跑的 ,因为这是菊花图,既然在其之前没了,那么肯定是没路了
                 //但是因为中间就一个节点,其他地方随便跑
                 //只要还不在一个并查集, 那么肯定有路
                 //而在一个并查集中,那这两个点肯定不能互相抵达了
                 //也就是说对于菊花图,
                 //用数字来决定点的顺序
                 //但是由点来决定能不能跑  
                 //要是两个点在同一个并查集里
                 //那么这两个"点"之间的边肯定被走过了
                 //所以说这个"数字"只能去别的点(并查集以外了)
                 //所以说,这个点就是在确定可以往哪跑
                 //毕竟倘若自己所在的 “点”已经被vis了,那么自己现在肯定处于这个并查集和其他自由区域的
                 //交界处,也就是其他的随便走 
                com(now[i],j);
                 break;
            }
        }
        cout<<"S";
        for(int j=1;j<=n;++j){
            cout<<vis[j]<<" ";
        } 
        cout<<endl;
    }
    for(int i=1;i<n;++i){
        cout<<put[now[i]]<<" ";
    }       
    for(int i=1;i<=n;++i){
        if(!vis[i]){
            cout<<i<<endl;
            break;
        }
    }       
}
int main(){
    scanf("%d",&t);
    while(t--){
        p=0;
        scanf("%d",&n);
        Aimee=0;
        for(int i=1;i<=n;++i){
            scanf("%d",&x);
            du[i]=0;
            zn[x]=i;
            head[i]=0;
            ans[i]=0x7ffffff;
        }
        for(int i=1;i<n;++i){
            scanf("%d%d",&x,&y);
            add(x,y);
        }
            flower();
    }
    return 0;
}


这东西没有啥额外的思维难度

主要就是贪心的想法

对于每一个点,送到可行的最小编号的点上,那么问题不大

就是会得到一个边的删除先后问题的问题

??先后,拓扑排序检查是否合法

那就没有代码了。

100pts

思路很好想?细节恶心

参考了此位大佬

#include<iostream>
#include<cstdio> 
#include<algorithm>
#include<cstring>
#define int long long
using namespace std;
int n;
int t;
int head[2501];
int zn[2005];
int tem[2051];
struct ed{
    int f;
    int to;
    int ne;
    int v;
} e[(2000<<1)+5];
int p;
int fa[2051]; 
int siz[2501];
int x,y,z;
int len[2505][2005],pre[2005][2005],nex[2005][2005],rt[2005][2005][2]; 
int put[2005];
int Aimee;
void add(int f, int to){
    siz[f]++;
    siz[to]++;
    e[++p].ne=head[f];
    e[p].to=to;
    head[f]=p;
    e[++p].ne=head[to];
    e[p].to=f;
    head[to]=p;
    return ;
}
void begin(){
    for(int i=1;i<=n+1;++i){
        for(int j=1;j<=n+1;++j)
        len[i][j]=nex[i][j]=pre[i][j]=rt[i][j][0]=rt[i][j][1]=0;
    }
    for(int i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y);
        rt[x][y][0]=rt[x][y][1]=y;
        rt[y][x][0]=rt[y][x][1]=x;
        len[x][y]=len[y][x]=1;
    }
}
void find(int now,int la){
    int l=rt[now][la][0],r=rt[now][la][1],ll,rr;
    int v;
    if(la==n+1){
        for(int i=head[now];i;i=e[i].ne){
            v=e[i].to;
            ll=rt[now][v][0],rr=rt[now][v][1];
            if(ll!=v||(pre[now][la]==rr&&len[now][ll]<siz[now]))
            continue;
            find(v,now);
        }
    }else{
        if(la==r){
            if(pre[now][n+1]==0&&(nex[now][n+1]!=l||len[now][l]==siz[now]))
            Aimee=min(Aimee,now);
            for(int i=head[now];i;i=e[i].ne){
                v=e[i].to;
                ll=rt[now][v][0],rr=rt[now][v][1];
                if(l==ll||ll!=v||nex[now][n+1]==v)
                continue;
                if(nex[now][n+1]==l&&pre[now][n+1]==rr&&len[now][l]+len[now][ll]<siz[now]){
                    continue;
                }
                find(v,now);
            }
        }
        else find(nex[now][la],now);
    }
}
void com(int now,int h,int t){
    int ll=rt[now][h][0],rr=rt[now][t][1];
    nex[now][h]=t;
    pre[now][t]=h;
    for(int i=ll;i&&i!=n+1;i=nex[now][i]){
        rt[now][i][0]=ll;
        rt[now][i][1]=rr;
    }
    len[now][ll]+=len[now][t];
}
bool mark(int now,int la){
    if(now==Aimee){
        pre[now][n+1]=la;
        nex[now][la]=n+1;
        return 1;
    }
    int v;
    int l=rt[now][la][0],r=rt[now][la][1],ll,rr;
    if(la==n+1){
        for(int i=head[now];i;i=e[i].ne){
            v=e[i].to;
            ll=rt[now][v][0],rr=rt[now][v][1];
            if(ll!=v||(pre[now][la]==rr&&len[now][ll]<siz[now]))
            continue;
            if(mark(v,now)){
                nex[now][n+1]=v;
                pre[now][v]=n+1;
                return 1;
            }
        }
    }else{
        if(la==r){
            for(int i=head[now];i;i=e[i].ne){
                v=e[i].to;
                ll=rt[now][v][0],rr=rt[now][v][1];
                if(l==ll||ll!=v||nex[now][n+1]==v)
                continue;
                if(nex[now][n+1]==l&&pre[now][n+1]==rr&&len[now][l]+len[now][ll]<siz[now]){
                    continue;
                }
                if(mark(v,now)){
                    com(now,la,v);
                    return 1;
                }
            }
        }else
        mark(nex[now][la],now) ;
    }
} 
signed main(){
    scanf("%d",&t);
    while(t--){
        p=0;
        scanf("%d",&n);
        for(int i=1;i<=n;++i){
            scanf("%d",&zn[i]);
            siz[i]=0;       
            head[i]=0;
        }
        begin();
        if(n==1){
            cout<<1<<endl;
            continue;
        }
        for(int i=1;i<=n;++i){
            Aimee=n+1;
            find(zn[i],n+1);
            mark(zn[i],n+1);
            cout<<Aimee<<" "; 
        }
        cout<<endl;
    }
    return 0;
}
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇