Codeforces Round #427F && 835F - Roads in the Kingdom

F. Roads in the Kingdom
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

In the Kingdom K., there are n towns numbered with integers from 1 to n. The towns are connected by n bi-directional roads numbered with integers from 1 to n. The i-th road connects the towns ui and vi and its length is li. There is no more than one road between two towns. Also, there are no roads that connect the towns with itself.

Let’s call the inconvenience of the roads the maximum of the shortest distances between all pairs of towns.

Because of lack of money, it was decided to close down one of the roads so that after its removal it is still possible to reach any town from any other. You have to find the minimum possible inconvenience of the roads after closing down one of the roads.
Input

The first line contains the integer n (3 ≤ n ≤ 2·105) — the number of towns and roads.

The next n lines contain the roads description. The i-th from these lines contains three integers ui, vi, li (1 ≤ ui, vi ≤ n, 1 ≤ li ≤ 109) — the numbers of towns connected by the i-th road and the length of the i-th road. No road connects a town to itself, no two roads connect the same towns.

It’s guaranteed that it’s always possible to close down one of the roads so that all the towns are still reachable from each other.
Output

Print a single integer — the minimum possible inconvenience of the roads after the refusal from one of the roads.

Examples
Input
3
1 2 4
2 3 5
1 3 1

Output
5

Input
5
2 3 7
3 1 9
4 1 8
3 5 4
4 5 5

Output
18

題目大意:給一棵環套樹,要求刪掉一條邊後樹的直徑最小。3<=n<=2e5


第一次看英文題解QwQ 竟然不用翻譯 好像比想象中容易多啦
找出環(令環長爲k)後,我們O(n)枚舉刪除環上的哪一條邊,O(1)計算直徑。
pref_diam[i]表示在環上的第1個節點到第i個節點及它們的子樹中 點對最大的距離
suff_diam[i]表示在環上的第i個節點到第k個節點及它們的子樹中 點對最大的距離
pref_dis[i]表示在環上的第1個節點到第i個節點及它們的子樹中 與環上的第一個點最大的距離
suff_dis[i]表示在環上的第i個節點到第k個節點及它們的子樹中 與環上的第一個點最大的距離
以上可以O(n)預處理出來,具體實現看代碼。
然後Ans=min(Ans,max(pref_diam[i],suff_diam[i+1],pref_dis[i]+suff_dis[i+1])
最後一定不要忘記Ans=max(所有環上的節點的子樹的直徑的最大值,Ans)
還有記得開long long


附Codeforece上題解
Observation I.

The given graph is a cycle with hanged trees. So, we can remove the edge only from the cycle, the resulting graph will be a tree.

Observation II.

We can minimize the distances only between the pairs of vertexes such that path between them goes through the cycle’s edges. Let’s say that these pairs are interesting.

Solution.

Let’s find the cycle using dfs. Let its length be k. Let’s number the vertices in it from 1 to k in round order. We will try to remove edges between 1 and 2, 2 and 3, …, 1 and k and calculate the maximum distance between the interesting pairs.

We need to pre-compute the following:

di — the maximum depth of the tree hanged to the i-th vertex of the cycle.
wi — the length of the edge between the i-th vertex of the cycle and the next in the round order.
pref_diami — the maximum distance between the interesting pairs such that their vertexes are in the trees hanged to the vertexes 1, 2, ..., i of the cycle.
suff_diami — the maximum distance between the interesting pairs such that their vertexes are in the trees hanged to the vertexes i, i + 1, ..., k of the cycle.
pref_fari — the maximum distance from the first vertex of the cycle to the vertexes that are in the trees hanged to the vertexes 1, 2, ..., i of the cycle.
suff_fari — the maximum distance from the first vertex of the cycle to the vertexes that are in the trees hanged to the vertexes i, i + 1, ..., k of the cycle.

Also suff_diamk + 1 = suff_fark + 1 =  - ∞.

These pre-computations can be done in linear time.

If we delete the edge between the i-th vertex of the cycle and the next in the round order, then the maximum distance between the interesting pairs is max(pref_far[i] + suff_far[i + 1], pref_diam[i], suff_diam[i + 1]).

After we found the optimal edge to remove, we remove it and find the diameter of the resulting tree. It can be done with 2 dfs’es. Let vertex v be the farest from 1. Let vertex u be the farest from v. It’s easy to prove that the path between u and v is the diameter.

Time complexity: O(n). Memory complexity: O(n).


#include <bits/stdc++.h>
#define N 200010
#define ll long long
#define INF 1000000000000000010
using namespace std;
int n,fir[N],nxt[N<<1],to[N<<1],l[N<<1],tot(1),cir[N],cnt(0),len[N],len_;
int fa[N],fl[N],h(0),t,vis[N],isc[N];
ll pdiam[N],sdiam[N],pdis[N],sdis[N],ans(INF),d[N],diam(0);

template <class Aqua>
inline void read(Aqua &s){
    s=0; char c=getchar();
    while (!isdigit(c)) c=getchar();
    while (isdigit(c)) s=s*10+c-'0',c=getchar();
}

inline void add(int u,int v,int w){
    to[++tot]=v; nxt[tot]=fir[u]; fir[u]=tot; l[tot]=w;
}

void find(int x,int f){
    fa[x]=f; vis[x]=1;
    for (int i=fir[x];i;i=nxt[i])
        if (to[i]!=f){
            if (vis[to[i]]){
                if (!h)
                    t=x,h=to[i],len_=l[i];
            }
            else
                find(to[i],x),fl[to[i]]=l[i];
        }
}

ll dfs(int x,int f){
    ll dep=d[x],mx=0,mx_=0,t;
    for (int i=fir[x];i;i=nxt[i])
        if (to[i]!=f && !isc[to[i]]){
            d[to[i]]=d[x]+l[i];
            t=dfs(to[i],x);
            dep=max(t,dep);
            t-=d[x];
            if (t>=mx)
                mx_=mx,mx=t;
            else
                mx_=max(mx_,t);
        }
    diam=max(diam,mx+mx_);
    return dep;
}

void calc(){
    ll mx,L=len[1];
    mx=pdiam[1]=d[cir[1]];
    for (int i=2;i<=cnt;L+=len[i++]){
        pdiam[i]=max(pdiam[i-1],mx+L+d[cir[i]]);
        mx=max(mx,d[cir[i]]-L);
    }
    L=len[cnt-1];
    mx=sdiam[cnt]=d[cir[cnt]];
    for (int i=cnt-1;i;L+=len[--i]){
        sdiam[i]=max(sdiam[i+1],mx+L+d[cir[i]]);
        mx=max(mx,d[cir[i]]-L);
    }

    L=len[1];
    pdis[1]=d[cir[1]];
    for (int i=2;i<=cnt;L+=len[i++])
        pdis[i]=max(pdis[i-1],d[cir[i]]+L);
    L=len[cnt];
    for (int i=cnt;i;L+=len[--i])
        sdis[i]=max(sdis[i+1],d[cir[i]]+L);
}

void solve(){
    for (int i=1;i<=cnt;i++)
        ans=min(ans,max(pdis[i]+sdis[i+1],max(pdiam[i],sdiam[i+1])));
}

int main(){
    read(n);
    int u,v,w;
    for (int i=1;i<=n;i++){
        read(u),read(v),read(w);
        add(u,v,w),add(v,u,w);
    }
    find(1,0);
    for (int i=t;i!=h;i=fa[i])
        len[++cnt]=fl[i],cir[cnt]=i,isc[i]=1;
    len[++cnt]=len_,cir[cnt]=h,isc[h]=1;
    for (int i=1;i<=cnt;i++)
        d[cir[i]]=dfs(cir[i],0);
    calc();
    solve();
    printf("%lld\n",max(diam,ans));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章