Gym

来源:互联网 发布:万能网络视频下载器 编辑:程序博客网 时间:2024/05/20 13:14

Problem A
Adjoin the Networks

Problem ID: adjoin


One day your boss explains to you that he has a
bunch of computer networks that are currently unreachable
from each other, and he asks you, the cable expert’s
assistant, to adjoin the networks to each other using
new cables. Existing cables in the network cannot be
touched.
He has asked you to use as few cables as possible,
but the length of the cables used does not matter to
him, since the cables are optical and the connectors are
the expensive parts. Your boss is rather picky on cable
usage, so you know that the already existing networks
have as few cables as possible.
Due to your humongous knowledge of computer networks, you are of course aware that the
latency for an information packet travelling across the network is proportional to the number of
hops the packet needs, where a hop is a traversal along a single cable. And since you believe a
good solution to your boss’ problem may earn you that long wanted promotion, you decide to
minimise the maximum number of hops needed between any pair of network nodes.


Input

On the first line, you are given two positive integers, the number 1 <= c <= 10^5 of computers and
the number 0 <= e <= c - 1 of existing cables. Then follow ` lines, each line consisting of two
integers a and b, the two computers the cables connect. You may assume that every computer
has a unique name between 0 and n - 1.


Output

The maximum number of hops in the resulting network.


Sample Input 1     Sample Output 1

6 4                                                             3
0 1
0 2
3 4
3 5

Sample Input 2     Sample Output 2

11 9                                                          4
0 1
0 3
0 4
1 2
5 4
6 4
7 8
7 9
7 10


Source

NCPC 2015 Problem A: Adjoin the Networks

Gym - 100781A


My Solution

题意:给出一个有c个节点e条边的无向图,求添加尽可能少的边使得图连通,并且图的半径(所有点对的最短路径的最大值)尽可能小。


无向图的直径、连通性

先把每个连通块的直径求出来,

//这里求直径的方法是 先随机选一个点然后找出距离这个点最远的点,然后选取该点x 作为起点,求距离x最远的点,路径dist[x-y]就是该连通块的直径了。

然后如果只有一个连通块,那该直径就是最终的直径

如果有2个连通块则,可以把他们的终点连起来

如果3个及以上,则先把最大的和第二大的连起来,然后后面的都连到最大的那个连通块的直接中点,

并且判断 (半径[第二大]+半径[第i大] + 2) 与 半径[第一大]+半径[第二大] +1 的大小。

然后还有考虑,所有的综合出来的新直径都小于最大的那个 连通块直径,即最后加一个 ans = max(ans, longist[max]);

时间复杂度 O(nlogn)

空间复杂度 O(V + E)


#include <iostream>#include <cstdio>#include <queue>#include <vector>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;typedef pair<LL, LL> ii;const LL MAXN = 1e5 + 8;const LL INF = 9e18 + 8;vector<ii> sons[MAXN];LL dis[MAXN];bool vis[MAXN];priority_queue<ii, vector<ii>, greater<ii> > pq;//O(nlogn)inline void dijkstra(vector<LL> &now, LL src){    LL sznow = now.size();    for(LL i = 0; i < sznow; i++){        dis[now[i]] = INF;        vis[now[i]] = false;    }    dis[src] = 0;while(!pq.empty()) pq.pop();pq.push(ii(0, src));LL u, v, w, d, sz, i;while(!pq.empty()){        u = pq.top().second;        d = pq.top().first;        pq.pop();        if(vis[u]) continue;        vis[u] = true;        sz = sons[u].size();for(i = 0; i < sz; i++){v = sons[u][i].first;w = sons[u][i].second;if(d + w < dis[v]){dis[v] = d + w;pq.push(ii(dis[v], v));}}}}vector<LL> now, rad;bool f[MAXN];inline void dfs(LL u, LL fa){    if(f[u]) return;    f[u] = true;    now.push_back(u);    LL sz = sons[u].size(), i, v;    for(i = 0; i < sz; i++){        v = sons[u][i].first;        if(v == fa) continue;        dfs(v, u);    }}int main(){    #ifdef LOCAL    freopen("a.txt", "r", stdin);    //freopen("a.txt", "w", stdout);    LL T = 1;    while(T--){    #endif // LOCAL    ios::sync_with_stdio(false); cin.tie(0);    LL n, m, src, e, u, v, w = 1, i, j, sznow, longist, longistu, ans = 0;    cin >> n >> m;    while(m--){        cin >> u >> v;        sons[u].push_back(ii(v, w));        sons[v].push_back(ii(u, w));    }    for(i = 0; i < n; i++){        if(f[i]) continue;        now.clear();        dfs(i, -1);        sznow = now.size();        if(sznow == 1){            rad.push_back(0);            longist = 0;        }        else{            dijkstra(now, now[0]);            longist = 0, longistu = -1;            for(j = 0; j < sznow; j++){                if(dis[now[j]] > longist){                    longist = dis[now[j]];                    longistu = now[j];                }            }            dijkstra(now, longistu);            longist = 0;            for(j = 0; j < sznow; j++){                longist = max(longist,  dis[now[j]]);            }            rad.push_back(longist);        }        //cout << longist << endl;    }    sort(rad.begin(), rad.end());    sznow = rad.size();    if(sznow == 1){        ans = rad[0];    }    else if(sznow == 2){        ans = (rad[sznow-1]+1) / 2 + (rad[sznow-2]+1) / 2 + 1;    }    else{        ans = (rad[sznow-1]+1) / 2 + (rad[sznow-2]+1) / 2 + 1;        for(i = sznow - 3; i >= 0; i--){            ans = max(ans, (rad[i]+1)/2 + (rad[sznow-2]+1)/2 + 2);        }    }    ans = max(ans, rad[sznow-1]);    cout << ans << endl;    #ifdef LOCAL    cout << endl;    }    #endif // LOCAL    return 0;}


  Thank you!

                                                                                                                                             ------from ProLights

原创粉丝点击