• poj1984 带权并查集


    题意:有多个点,在平面上位于坐标点上,给出一些关系,表示某个点在某个点的正东/西/南/北方向多少距离,然后给出一系列询问,表示在第几个关系给出后询问某两点的曼哈顿距离,或者未知则输出-1。

    只要在元素的权值上保存两个信息,与祖先元素的两个方向的差,我选择正东和正北方向差(负值表示正西和正南),然后直接用带权并查集,询问时曼哈顿距离就是两个权值的绝对值之和。由于询问是嵌在给出关系中间的,所以要先存下所有关系和询问,离线做就行。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 using namespace std;
     5 const int maxm=4e4+10;
     6 
     7 int fa[maxm],north[maxm],east[maxm];
     8 int a[maxm],b[maxm],l[maxm],ans[10005];
     9 char s[maxm][3];
    10 struct que{
    11     int num,a,b,t;
    12     bool operator < (const que a)const{
    13         return t<a.t;
    14     }
    15 }q[10005];
    16 
    17 int abs(int a){return a>0?a:-a;}
    18 
    19 void init(int n){
    20     for(int i=1;i<=n;++i){
    21         fa[i]=i;
    22         north[i]=east[i]=0;
    23     }
    24 }
    25 
    26 int find(int x){
    27     int r=x,t1,t2,t3,cn=0,ce=0;
    28     while(r!=fa[r]){
    29         cn+=north[r];
    30         ce+=east[r];
    31         r=fa[r];
    32     }
    33     while(x!=r){
    34         t1=fa[x];
    35         t2=cn-north[x];
    36         t3=ce-east[x];
    37         north[x]=cn;
    38         east[x]=ce;
    39         fa[x]=r;
    40         cn=t2;
    41         ce=t3;
    42         x=t1;
    43     }
    44     return r;
    45 }
    46 
    47 int main(){
    48     int n,m;
    49     scanf("%d%d",&n,&m);
    50     init(n);
    51     for(int i=1;i<=m;++i)scanf("%d%d%d%s",&a[i],&b[i],&l[i],s[i]);
    52     int k;
    53     scanf("%d",&k);
    54     for(int i=1;i<=k;++i){
    55         scanf("%d%d%d",&q[i].a,&q[i].b,&q[i].t);
    56         q[i].num=i;
    57     }
    58     sort(q+1,q+k+1);
    59     int pos=1;
    60     for(int i=1;i<=m;++i){
    61         int x=find(a[i]),y=find(b[i]);
    62         int Cn=0,Ce=0;
    63         if(s[i][0]=='N')Cn=l[i];
    64         else if(s[i][0]=='S')Cn=-l[i];
    65         else if(s[i][0]=='E')Ce=l[i];
    66         else if(s[i][0]=='W')Ce=-l[i];
    67         if(x!=y){
    68             fa[x]=y;
    69             north[x]=north[b[i]]+Cn-north[a[i]];
    70             east[x]=east[b[i]]+Ce-east[a[i]];
    71         }
    72         
    73         while(q[pos].t==i&&pos<=k){
    74             x=find(q[pos].a);
    75             y=find(q[pos].b);
    76             if(x!=y)ans[q[pos].num]=-1;
    77             else ans[q[pos].num]=abs(north[q[pos].a]-north[q[pos].b])+abs(east[q[pos].a]-east[q[pos].b]);
    78             pos++;
    79         }
    80     }
    81     for(int i=1;i<=k;++i)printf("%d
    ",ans[i]);
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    Java 9 揭秘(9. 打破模块封装)
    Java 9 揭秘(8. JDK 9重大改变)
    好书分享 ——《深度工作》
    Java 9 揭秘(7. 创建自定义运行时映像)
    Java 9 揭秘(6. 封装模块)
    如何更好地管理你的精力,时间和专注力实现最佳表现
    这是您一直期待的所有iOS 11功能的屏幕截图
    我为什么不敢也不想写自己的经验和想法?
    无聊? 现在你知道为什么了!
    Java 9 揭秘(5. 实现服务)
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/4790233.html
Copyright © 2020-2023  润新知