Summer exams 5: tree minimum spanning tree (MST + minimum multiplier)

topic:

analysis:

Conversion issues: first obtaining a minimum spanning tree
for the non-tree edge, the non-attached side of the tree will be a ring, but can be non-tree edge side of the tree that is the ring max-1
for the side of the tree is it can not be infinitely increased, due to the impact of non-tree edges, and the answer is that it can affect non-tree edges min-1

The first requires only a maximum chain, with a doubling solve
the second: For each non-tree edge, we must update a chain, but you can not write a sectional chain
practices: non-tree edge from small to large sorted, apparently a first side is a small update, will not be big update, so open a ff array
represents a depth shallower than it point to point in that path (without root) has been updated when the non-enumeration tree edge to update when the skip has been updated
to ensure that each edge is updated only once

/ * 
First find a minimum spanning tree 
for the non-tree edge, the non-attached side of the tree will be a ring, but can be non-tree edge side of the tree that is the ring max-1 
for the side of the tree, the it can not be infinitely increased, due to the impact of non-tree edges, and the answer is min-1 it can affect non-tree edges of 
the first strand just claim maximum doubling solution with 
the second: for each non-tree edge, it must update a chain, but you can not write a sectional chain 
practices: non-tree edge from small to large sorted, apparently a first side updates are small, and it will not be a big update, so open a ff array 
represents a point shallower than the depth to which that path points (without roots) has been updated when the non-tree edge to enumerate the update has been updated skipped 
ensures that each edge is updated only once 
* / 
#include <bits / STDC ++ H.>
 the using  namespace STD;
 #define INF 1,000,000,001
 #define N 100005
 int head [N], W [N << . 1 ], to [N << . 1 ], NEX [N << . 1 ], TOT = 0 , FA [N], ANS [N], ID [N << . 1 ];
 int F [N] [30],mx[N][30],dep[N],num[N],s[N],ff[N],fl[N],n,m;
struct node{ int u,v,w,o,ans; }e[N];
bool cmp1(const node &a,const node &b) { return a.w<b.w; }
bool cmp2(const node &a,const node &b) { return a.o<b.o; }
void add(int a,int b,int ww,int i) { to[++tot]=b; nex[tot]=head[a]; w[tot]=ww; id[tot]=i; head[a]=tot; }
int find(int x)
{
    IF (FA [X] == X) return X;
     return FA [X] = Find (FA [X]); 
} 
void DFS ( int U) 
{ 
    for ( int I = head [U]; I; I = NEX [I]) {
         int V = to [I];
         IF (V == F [U] [ 0 ]) Continue ; 
        F [V] [ 0 ] = U; DEP [V] DEP = [U] + . 1 ; 
        MX [V] [ 0 ] = W [I]; NUM [V] = ID [I]; // ID upward even record the point corresponding to the discharge side of the good sequence number 
        for ( int J = . 1 ; J <= 20;j++) f[v][j]=f[f[v][j-1]][j-1];
        for(int j=1;j<=20;j++) mx[v][j]=max(mx[f[v][j-1]][j-1],mx[v][j-1]);
        dfs(v);
    }
}
int lca(int a,int b)
{
    if(dep[a]>dep[b]) swap(a,b);
    for(int i=20;i>=0;i--) if(dep[f[b][i]]>=dep[a]) b=f[b][i];//=!!
    if(a==b) return a;
    for(int i=20;i>=0;i--) if(f[a][i]!=f[b][i]) a=f[a][i],b=f[b][i];
    return f[a][0];
}
int lca_max(int a,int b,int lc)
{
    int anss=-1;
    if(dep[a]>dep[b]) swap(a,b);
    for(int i=20;i>=0;i--) if(dep[f[b][i]]>=dep[a]) anss=max(anss,mx[b][i]),b=f[b][i];//先更新再跳 一定要有dep>=!! 
    if(a==b) return anss;
    for(int i=20;i>=0;i--) if(f[a][i]!=f[b][i]) anss=max(anss,max(mx[a][i],mx[b][i])),a=f[a][i],b=f[b][i];
    anss=max(anss,max(mx[a][0],mx[b][0]));
    return anss;
}
void work(int u,int lc,int ww)
{
    while(dep[u]>dep[lc]){
        if(!s[num[u]] || s[num[u]]>ww) s[num[u]]=ww;//更新最小值 
        FF [u] = LC; u = f [u] [ 0 ]; // record where u been updated a point u must = fa [u] otherwise it will not move in place 
        the while (FF [u] =! U) = U FF [U]; 
    } 
} 
int main () 
{ 
    The freopen ( " tree.in " , " R & lt " , stdin); 
    The freopen ( " tree.out " , " W " , stdout);
     int A, B , WW; 
    Scanf ( " % D% D " , & n-, & m);
     for ( int I = . 1 ; I <= m;i++ ) {
        scanf("%d%d%d",&a,&b,&ww);
        e[i].u=a,e[i].v=b,e[i].w=ww,e[i].o=i;
    }
    sort(e+1,e+1+m,cmp1);
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        int f1=find(e[i].u),f2=find(e[i].v);
        if(f1==f2) continue;
        fa[f1]=f2; fl[i]=1; 
        add (e [i] .u, e [i] .v, e [i] .w, i); add (e [i] .v, e [i] .u, e [i] .w, i ); 
    } 
    DEP [ . 1 ] = . 1 ; 
    DFS ( . 1 );
     for ( int I = . 1 ; I <= n-; I ++) FF [I] = I; // FF record array update each point where a point initially for its own   
    for ( int I = . 1 ; I <= m; I ++ ) {
         IF (FL [I]) Continue ;
         int U = E [I] .u, V = E [I] .v, WW = E [I] .W;
         int LC LCA = (U, V), Maxx = lca_max (U, V, LC); 
        ANS [I] = maxx- . 1 ; // ANS non-tree edge value stored 
        the while (FF [U] ! = U) FF U = [U]; // jump directly to the position has been updated to 
        the while (FF [V] = V!) V = FF [V] ; 
        Work (u, LC, WW); // process a strand of u to v is updated to the minimum value of the non-tree edges 
        Work (v, LC, WW); 
    } 
    for ( int I = . 1 ; I <= m ; I ++ ) {
         IF ! (FL [I]) E [I] .ans = ANS [I];
         the else E [I] .ans = S [I] - . 1 ; 
    } 
    Sort (E + . 1 , E + . 1 + m , CMP2);
     for ( int I = . 1 ; I <= m; I ++) the printf ( " % D \ n- " , E [I] .ans); / ** / 
}
/*
4 4 
2 1 2 
3 2 2 
4 3 2 
1 4 3

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

*/

 

Guess you like

Origin www.cnblogs.com/mowanying/p/11420174.html