问题 L: 分糖果(candy)

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

第二行为一个数m,表示小朋友吃糖的时间。

下面p行每行两个整数,表示某两个小朋友在彼此身旁。

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

样例输入
4 3 1
2
1 2
2 3
1 4
样例输出
5
提示

【样例解释】

第一秒,糖在1手上。第二秒,糖传到了2、3的手中。第三秒,糖传到了4的手中,此时1吃完了。第四秒,2、3吃完了。第五秒,4吃完了。所以答案是5。

【限制】

40%的数据满足:1≤n≤100

60%的数据满足:1≤n≤1000

100%的数据满足:1≤n≤100000

m≤n*(n-1)/2,不会有同一个关系被描述多次的情况。

解法一:bfs树的层数+m记为正解

#include
#define maxn 100005
#define maxm 2000000
using namespace std;
struct node{
    int to;
    int next;
    int quan;
    int d;
}edge[maxm];
struct no{
    int u;
    int d;
};
int n, m, c, p, cnt;
int head[maxn], book[maxn];
void add(int u, int v, int w){
    edge[cnt].to = v;
    edge[cnt].quan = w;
    edge[cnt].next = head[u];
    head[u] = cnt ++;
}
int main()
{
    int u, v, ans = 0;
    scanf("%d %d %d", &n, &p, &c);
    scanf("%d", &m);
    memset(head, -1, sizeof(head));
    for(int i = 1 ; i <= p ; ++ i){
        scanf("%d %d", &u, &v);
        add(u, v, m); add(v, u, m);
    }
    queue<no> que;
    no st;
    st.d = 1;
    st.u = c;
    que.push(st);
    while(!que.empty()){
        no t = que.front();
        que.pop();
        for(int i = head[t.u] ; i != -1 ; i = edge[i].next){
            int tt = edge[i].to;
            if(book[t.u] && book[tt]) continue;
            else{
                book[tt] = 1; book[t.u] = 1;
                ans = max(ans, t.d + 1);
                no temp;
                temp.d = t.d + 1; temp.u = tt;
                que.push(temp);
            }
        }


    }
    cout<<ans + m;
    return 0;
}

解法二:堆优化的dijistra

#include
#define INF 0x3f3f3f3f
#define maxn 2000005
#define maxm 100005
using namespace std;
struct node{
    int to;
    int quan;
    int next;
}edge[maxn];
int n, m, sum, ans, cnt, p, c;
int head[maxm], book[maxm], dis[maxm];
int h[maxm], pos[maxm], siz;
void add(int u, int v, int w){
    edge[cnt].to = v;
    edge[cnt].quan = w;
    edge[cnt].next = head[u];
    head[u] = cnt ++;
}
void init(){
    siz = n;
    for(int i = 1 ; i <= siz ; ++ i){
        pos[i] = i; h[i] = i;
    }
}
void siftdown(int i){
    int flag = 0, t;
    while(i * 2 <= siz && !flag){
        if(dis[h[i]] > dis[h[i * 2]])
            t = i * 2;
        else
            t = i;
        if(i * 2 + 1 <= siz){
            if(dis[h[i * 2 + 1]] < dis[h[t]])
                t = i * 2 + 1;
        }
        if(t != i){
            swap(h[t], h[i]);
            swap(pos[h[t]], pos[h[i]]);
            i = t;
        }
        else flag = 1;
    }
}
void siftup(int i){
    int flag = 0;
    if(i == 1) return;
    while(i != 1 && !flag){
        if(dis[h[i]] < dis[h[i / 2]]){
            swap(h[i], h[i / 2]);
            swap(pos[h[i]], pos[h[i / 2]]);
        }
        else flag = 1;
        i /= 2;
    }
}
void heap(){
    for(int i = siz / 2 ; i >= 1 ; i --){
        siftdown(i);
    }
}
int pop(){
    int t;
    t = h[1];
    pos[t] = 0;
    h[1] = h[siz];
    pos[h[1]] = 1;
    siz --;
    siftdown(1);
    return t;
}
void diji()
{
    //book[1] = 1;
    //sum ++;
    while( 1 ){
        int mini = INF, t = -1;
        t = pop();
        if(siz == 0) break;
        book[t] = 1;
        sum ++; //ans += dis[t];
        for(int i = head[t] ; i != -1 ; i = edge[i].next){
            int tt = edge[i].to;
            if(dis[tt] > dis[t] + edge[i].quan && !book[tt]){
                dis[tt] = dis[t] + edge[i].quan;
                ans = max(ans, dis[tt]);
                siftup(pos[tt]);
            }
        }
    }
}
int main()
{
    int u, v, w;
    memset(head, -1, sizeof(head));
    scanf("%d %d %d", &n, &p, &c);
    scanf("%d", &m);
    for(int i = 1 ; i <= n ; ++ i) dis[i] = INF;
    for(int i = 1 ; i <= p ; ++ i){
        scanf("%d %d", &u, &v);
        add(u, v, 1); add(v, u, 1);
    }
    /*for(int i = head[1] ; i != -1 ; i = edge[i].next){
        int tt = edge[i].to;
        dis[tt] = min(dis[tt], edge[i].quan);
    }*/
    dis[c] = 0;
    init();
    heap();
    diji();
    cout<<ans + m + 1;
    return 0;
}

解法三:spfa

#include
#define INF 0x3f3f3f3f
#define maxn 2000005
#define maxm 100005
using namespace std;
struct node{
    int to;
    int quan;
    int next;
}edge[maxn];
int n, m, sum, ans, cnt, p, c;
int head[maxm], book[maxm], dis[maxm];
void add(int u, int v, int w){
    edge[cnt].to = v;
    edge[cnt].quan = w;
    edge[cnt].next = head[u];
    head[u] = cnt ++;
}
int main()
{
    int u, v, w;
    memset(head, -1, sizeof(head));
    scanf("%d %d %d", &n, &p, &c);
    scanf("%d", &m);
    for(int i = 1 ; i <= n ; ++ i) dis[i] = INF;
    for(int i = 1 ; i <= p ; ++ i){
        scanf("%d %d", &u, &v);
        add(u, v, 1); add(v, u, 1);
    }
    queue<int> que;
    dis[c] = 0;
    book[c] = 1;
    que.push(c);
    while(!que.empty()){
        int k = que.front();
        que.pop();
        for(int i = head[k] ; i != -1 ; i = edge[i].next){
            int tt = edge[i].to;
            if(dis[tt] > dis[k] + edge[i].quan){
                dis[tt] = dis[k] + edge[i].quan;
                ans = max(ans, dis[tt]);
                if(!book[tt]){
                    que.push(tt);
                    book[tt] = 1;
                }
            }
        }
        book[k] = 0;
    }
    cout<<ans + m + 1;
    return 0;
}

你可能感兴趣的:(图论)