【图论】分糖果

5 篇文章 0 订阅

1009: 分糖果

Description
童年的我们,将和朋友分享美好的事物作为自己的快乐。这天,C小朋友得到了Plenty of candies,将要把这些糖果分给要好的朋友们。已知糖果从一个人传给另一个人需要1 秒的时间,同一个小朋友不会重复接受糖果。由于糖果足够多,如果某时刻某小朋友接受了糖果,他会将糖果分成若干份,分给那些在他身旁且还没有得到糖果的小朋友们,而且自己会吃一些糖果。由于嘴馋,小朋友们等不及将糖果发完,会在得到糖果后边吃边发。每个小朋友从接受糖果到吃完糖果需要m秒的时间。那么,如果第一秒C小朋友开始发糖,第多少秒所有小朋友都吃完了糖呢?

Input
多组测试数据。
第一行为三个数n、p、c,为小朋友数、关系数和C小朋友的编号。
第二行为一个数m,表示小朋友吃糖的时间。
下面p行每行两个整数,表示某两个小朋友在彼此身旁

Output
输出一个数,为所有小朋友都吃完了糖的时间

Sample Input

4 3 1
2
1 2
2 3
1 4

Sample Output
5

这个题有点水,不过主要是要理解题意,我总结出如下几点:
1.同一个人可以在同一时间将糖果分给所有人(一秒之内)。
2.同一时间可以有多个人进行分糖果操作。

理清这两点之后其实发现这个就是一个深度优先遍历问题,分别用队列保存每一秒的情况,队列为空时就已经讨论结束了。
这样的话就直接用bfs做吧。
最好用vector数组和queue队列优化一下。不会用的百度一下吧,说实话最近才发现vector这玩意儿还挺好用的哦。## 标题

AC代码:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<vector>
    using namespace std;
    vector<int>num[10001];//二维,一维只需要声明为vector<int>num
    queue<int>q;
    int vis[10001],f[10001];//vis标记,f为传递时间
    void bfs()
    {
        int i,t;
        while(!q.empty()){
            t=q.front();q.pop();
            for(i=0;i<num[t].size();i++){
                if(!vis[num[t][i]]){//对与t相连的各个元素进行搜索,这里的vis表明这个人是否分到糖
                    vis[num[t][i]]=1;
                    f[num[t][i]]=f[t]+1;//表示到第t个人分到糖果的时间,q:可以一次性分给多个人?
                    q.push(num[t][i]);//注意:1,传递糖果的过程是可以同时进行的。2:同一个人可以在同一时间传递给周围的所有人
                }//最优情况就是每次小朋友吃的时候所有有糖的小朋友发给周围所有人
            }
        }
    }
    int main()
    {
        int n,p,c,m,i,a,b;
        while(~scanf("%d%d%d%d",&n,&p,&c,&m))
        {
            for(i=0;i<=n;i++)num[i].clear();//数据清空
            memset(vis,0,sizeof(vis));
            memset(f,0,sizeof(f));
            while(!q.empty()) q.pop();//清空队列
            for(i=0;i<p;i++){
                scanf("%d%d",&a,&b);
                num[a].push_back(b);//动态数组的数据输入操作,存放a附件的人,如果不会用这个就联想一下队列吧
                num[b].push_back(a);
            }
            q.push(c);vis[c]=1;f[c]=1;//最先让c入队,fc=1为第一秒,大哥们看清楚题意,第一秒分给c,开始就被这里坑了
            bfs();int ans=0;
            for(i=1;i<=n;i++)if(f[i]>ans) ans=f[i];
            printf("%d\n",ans+m);//ans是传递完花费的时间,加上最后接到糖的小朋友们吃糖的时间就是最终答案
        }
        return 0;
    }
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值