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
  • 相关阅读:
    奇数阶魔方问题
    《DSP using MATLAB》示例9.3
    《DSP using MATLAB》示例9.2
    《DSP using MATLAB》示例9.1
    找个目标很重要
    《DSP using MATLAB》示例Example 8.30
    《DSP using MATLAB》示例Example 8.29
    《DSP using MATLAB》示例Example 8.28
    《DSP using MATLAB》示例Example 8.27
    《DSP using MATLAB》示例Example 8.26
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5064758.html
Copyright © 2011-2022 走看看