zoukankan      html  css  js  c++  java
  • [bzoj1576] [Usaco2009 Jan]安全路经Travel

      看了半天题解。。。。

      http://hzwer.com/4019.html    http://cxjyxx.me/?p=662

      神犇一句“不用多说”蒟蒻弄了半天TAT。。。但实在懒(bu)得(gan)写链剖= =

      接题解:

        对于当前非树边(u,v),设t=lca(u,v),这条非树边可以去尝试更新t-u和t-v(但不包括t)的最短路长度

        将非树边按权值(dis[u]+dis[v]+边的长度)排序后,如果一个点已被更新过就不用去试了(先更新的肯定答案更优)

        所以脑补一下就可以发现有时一些连续的点(曾祖父-祖父-父亲-.....)都被更新过,这些点都可以直接跳过。

        这时就用到了并查集。。father[i]表示点i所在的 被更新过的点组成的链 ,链最顶端的节点编号。(还没被更新过的话father[i]=0)

        接着就相当于联通块的合并,只是这里的“联通块”是树上的已被更新的点组成的链。

      并查集部分的复杂度是O(n*alpha(n))的。。。比起链剖来说高明到不知道哪里去了!

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<queue>
     5 #include<algorithm>
     6 using namespace std;
     7 const int maxn=100023;
     8 const int maxm=200233;
     9 struct edge{
    10     int u,v,val;
    11 }E[maxm];
    12 struct ZS{
    13     int pos,dis;
    14 };
    15 priority_queue<ZS>q;
    16 bool operator <(ZS a,ZS b){
    17     return a.dis>b.dis;
    18 }
    19 struct zs{
    20     int too,pre;
    21     short dis;
    22 }e[maxm<<1];
    23 int pre[maxn],last[maxn],dis[maxn],bel[maxn],father[maxn],fa[maxn],dep[maxn];
    24 bool used[maxn],intree[maxm<<1];
    25 int i,j,k,n,m,u,v,tot,TOT,a,b,c,tmpu,tmpv,lastu,lastv;
    26 int ra;char rx;
    27  
    28 inline int read(){
    29     rx=getchar();ra=0;
    30     while(rx<'0'||rx>'9')rx=getchar();
    31     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra;
    32 }
    33 inline void insert(int a,int b,int c){
    34     e[++tot].too=b;e[tot].dis=c;e[tot].pre=last[a];last[a]=tot;
    35     e[++tot].too=a;e[tot].dis=c;e[tot].pre=last[b];last[b]=tot;
    36 }
    37 void spfa(){
    38     int i,j,l,r,now,nowdis;
    39     ZS tmp;
    40     memset(dis,50,(n+1)<<2);
    41     tmp.pos=1;tmp.dis=0;q.push(tmp);dis[1]=0;dep[1]=1;
    42     while(!q.empty()){
    43         while(!q.empty()&&used[q.top().pos])q.pop();
    44         if(q.empty())break; 
    45         now=q.top().pos;used[now]=1;
    46         for(i=last[now];i;i=e[i].pre)if(dis[e[i].too]>dis[now]+e[i].dis){
    47             dis[e[i].too]=dis[now]+e[i].dis;pre[e[i].too]=i;fa[e[i].too]=now;
    48             dep[e[i].too]=dep[now]+1;
    49             tmp.pos=e[i].too,tmp.dis=dis[e[i].too],q.push(tmp);
    50         }
    51     }
    52 }
    53 bool cmp(edge a,edge b){
    54     return a.val<b.val;
    55 }
    56 int getfa(int x){
    57     if(father[x]){father[x]=getfa(father[x]);return father[x];}
    58     return x;
    59 }
    60 int main(){
    61     n=read();m=read();
    62     for(i=1;i<=m;i++)a=read(),b=read(),c=read(),insert(a,b,c);
    63     spfa();
    64     for(i=1;i<=n;i++)intree[pre[i]]=1;
    65     for(i=1;i<=tot;i+=2)if(!intree[i]&&!intree[i+1])
    66         E[++TOT].u=e[i+1].too,E[TOT].v=e[i].too,E[TOT].val=e[i].dis+dis[e[i].too]+dis[e[i+1].too];
    67     sort(E+1,E+1+TOT,cmp);
    68     for(i=1;i<=TOT;i++){
    69         u=E[i].u;v=E[i].v;
    70         tmpu=getfa(u);tmpv=getfa(v);lastu=lastv=0;
    71         while(tmpu!=tmpv){
    72             if(dep[tmpu]<dep[tmpv])swap(tmpu,tmpv),swap(u,v),swap(lastu,lastv);
    73             if(!bel[u]){
    74                 bel[u]=i;
    75                 if(lastu)father[lastu]=u;
    76             }else if(lastu)father[lastu]=tmpu;
    77             lastu=tmpu;u=fa[lastu];tmpu=getfa(u);
    78         }//u表示当前尝试更新的节点,tmpu表示u所在链的最顶端节点,lastu表示上一次更新的节点。
    79     }
    80     for(i=2;i<=n;i++)if(bel[i])printf("%d
    ",E[bel[i]].val-dis[i]);else printf("-1
    ");
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    解决:transform-decorators-legacy 报错
    leetcode刷题笔记 232题 用栈实现队列
    leetcode刷题笔记 231题 2的幂
    leetcode刷题笔记 230题 二叉搜索树中第K小的元素
    leetcode刷题笔记 229题 求众数II
    leetcode刷题笔记 228题 汇总区间
    leetcode刷题笔记 227题 基本计算器II
    leetcode刷题笔记 225题 用队列实现栈
    leetcode刷题笔记 224题 基本计算器
    leetcode刷题笔记 223题 矩形面积
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5064758.html
Copyright © 2011-2022 走看看