SMUSpring天梯赛1

补题1:龙龙送外卖

题意:

做法:思维--遍历方式,从输入的点往外卖点遍历,或标记过的点。回溯的时候更新深度!

//到达了最后一个送货点之后不用返回根结点.那么之前到达的点都是要折返点,那么就最后才送最深点节点。    //还有就是如果在去节点8点时候,途径了节点2,那么这个时候去节点2的路可以忽略,因为是顺路的。    //一边读入一边遍历,从输入的点开始,往上走.直到到达外卖站或到达一个被标记过的点,停止.    // 回溯的时候更新深度!! 而且dfs不是void类型,要返回该次点增加的代价.并且要更新deepest.输出sum-deepest即可.

int n,q,s,ans=0,deepest=0;
int fa[100005],depth[100005];
unordered_map<int,bool> mark;
int dfs(int cur,int d){
    if(cur==s||mark[cur]){
        deepest=max(deepest,depth[cur]+d);
        return 2*d;
    }
    int res=0;                          //res
    res+=dfs(fa[cur],d+1);
    depth[cur]=depth[fa[cur]]+1;
    mark[cur]=1;
    deepest=max(deepest,depth[cur]);
    return res;
}
void solve(){                       //补7-11--龙龙送外卖--思维-遍历方式
    //到达了最后一个送货点之后不用返回根结点.那么之前到达的点都是要折返点,那么就最后才送最深点节点。
    //还有就是如果在去节点8点时候,途径了节点2,那么这个时候去节点2的路可以忽略,因为是顺路的。
    //一边读入一边遍历,从输入的点开始,往上走.直到到达外卖站或到达一个被标记过的点,停止.
    // 回溯的时候更新深度!!
    cin>>n>>q;
    for(int i=1;i<=n;i++){
        int x;
        cin>>x;
        if(x==-1) s=i;
        else fa[i]=x;
    }
    while(q--){
        int x;
        cin>>x;
        ans+=dfs(x,0);
        cout<<ans-deepest<<endl;
    }
}

补题2:智能护理中心统计

题意:

10 23
EAST CNTR
ZJ EAST
SD EAST
WEST CNTR
SX WEST
HZ ZJ
JN SD
2 JN
8 JTH
6 XAHP
4 ZDYH
5 ZDYH
ZDYH HZ
HUZ ZJ
JX ZJ
1 JX
3 JN
WZ ZJ
XAHP XIAN
XIAN SX
YL SX
JTH XIAN
7 XAHP
Q EAST
T 1 YL
Q EAST
Q SX
T 8 ZDYH
Q HZ
Q HUZ
T 10 XAHP
Q CNTR
E

以上为输入。。

输出:

5
4
4
3
0
9

做法:首先要把输入第一次出现的机构先哈希h[机构]=curhash.如果输入的是机构+机构,那么按照高层向低层建图vct1.如果是人+机构,那么记录机构人数的mp2[机构]++且mp1[老人]=h[机构].但是因为输入可能不是一棵树,可能是森林,那么就有多个最高层机构(即根节点,入度为0).那么可以开一个mp3来判断,哪些出现过的机构,入度是0的。后面dfs遍历mp3中各个根节点,并且更新mp2的人数---到这里初始处理完成。之后读入操作。如果是Q,直接输出mp2[ask]。如果是转移,有两种可能,老人可能是新来的,原本不属于任何机构,那么只需要mp2向上增加。如果老人原本属于某个机构,那么原机构mp2向上减,新机构mp2向上增加.并且修改mp1为新机构。因为这里要低层向高层更新,刚才建图的vct1是高层向低层,那么需要回到上面输入再建一个图vct2,低层向高层。即vct1和vct2是反向的。不建为一个无向图是因为进行特定反向遍历的时候,不能分辨哪个点是高层,哪个是低层,所以干脆分开建图。                                                                                    赛后补题时候没有看题解,写的思路和赛时是完全一样的,但是比赛时更加清晰(没想到一发就过了,不用调错(只有dfs,mp2更新那里有一点错,一下就改正了))。赛时虽然思路是这么个思路,但是没有实现好,写的自己有点晕,导致没写出来,还是要保持高度专注和仔细吧。ps:这题更上一题""龙龙送外卖""都有dfs遍历,回溯的时候更新节点的值.

unordered_map<string,int> h;
vector<int> vct1[100005],vct2[100005];
unordered_map<int,int> mp1,mp2;  //mp1[老人]=机构  mp2[机构]=人数
unordered_map<int,bool> mp3;        //找到根节点
int curhash=0;
int dfs(int x){
    int res=0;
    for(auto v:vct1[x]){
        res+=dfs(v);
    }
    mp2[x]+=res;            //for之后更新现在的节点
    return mp2[x];
}
void up(int x,int op){
    if(op==1){    //加
        mp2[x]++;
        for(auto boss:vct2[x]) up(boss,1);
    }
    else{           //减
        mp2[x]--;
        for(auto boss:vct2[x]) up(boss,0);
    }
}
void solve(){             //补7-12 智能护理中心统计
    //先建机构和机构的关系树.关系树可能会是森林,可能有多个根节点-入度为0。每棵树都要进行处理.
    int n,m;
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        string str1,str2;
        cin>>str1>>str2;
        if(str1[0]>='1'&&str1[0]<='9'){            //人+机构
            if(h[str2]==0) h[str2]=++curhash;
            mp1[stoi(str1)]=h[str2];
            mp2[h[str2]]++;
        }
        else{                                       //机构+机构
            if(h[str1]==0) h[str1]=++curhash;
            if(h[str2]==0) h[str2]=++curhash;
            mp3[h[str1]]=1;
            if(mp3[h[str2]]==0) mp3[h[str2]]=0;
            vct1[h[str2]].emplace_back(h[str1]);    //高层到低层
            vct2[h[str1]].emplace_back(h[str2]);    //低层到高层
        }
    }
    for(auto m3:mp3){   //从根节点进入,往下dfs
        if(m3.second==0) dfs(m3.first);
    }
//    for(auto h0:h){
//        cout<<h0.first<<":"<<mp2[h0.second]<<endl;
//    }
    while(1){
        char op;
        cin>>op;
        if(op=='E') break;
        if(op=='Q'){
            string ask;
            cin>>ask;
            cout<<mp2[h[ask]]<<endl;
        }
        else{
            int per;
            string to;
            cin>>per>>to;
            if(mp1[per]==0){            //如果老人一开始没有所属
                up(h[to],1);  //加
                mp1[per]=h[to];
            }
            else{
                up(mp1[per],0);  //减
                up(h[to],1);   //加
                mp1[per]=h[to];      //更改老人的所属
            }
        }
    }
}
  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值