zoukankan      html  css  js  c++  java
  • HDU 4297One and One Story解题报告

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=4297

    这道题所给的图是一个森林,每一个子图都必有一个环(因为总边数为n),可以把环当做这棵树的根节点,那么如果两个点不在一棵树上,一定互相不可达,如果在一棵树上,如果两个点在同一棵子树上,那么一起到的点就是LCA,所以要维护森林的LCA,如果不在同一棵子树上,则要到各自的根节点,然后沿着环方向分别判断哪种情况是最优解。

    View Code
      1 #pragma comment(linker, "/STACK:10240000000,10240000000")
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<cmath>
      6 #define N 500005
      7 #define max(a,b) ((a)>(b)?(a):(b))
      8 #define min(a,b) ((a)<(b)?(a):(b))
      9 using namespace std;
     10 int nxt[N];
     11 int root[N];//点是否在环上,在环上是环上的第几个点
     12 int father[N];//在环上的父节点
     13 int num[N];//所在环的节点个数
     14 int f[N];//并查集判断是否是在一个树上,并且可以确定环
     15 int list[2*N];
     16 int fir[2*N],ti;//rmq解决LCA问题
     17 bool used[N];
     18 int deep[2*N];
     19 int n;
     20 int head[N],cnt;
     21 struct node
     22 {
     23     int v,next;
     24 };
     25 node edge[N];//要加反向边
     26 void add(int u,int v)
     27 {
     28     edge[cnt].v=v,edge[cnt].next=head[u],head[u]=cnt++;
     29 }
     30 int find(int x)
     31 {
     32     int r=x;
     33     while(r!=f[r])
     34     r=f[r];
     35     int t1;
     36     while(x!=f[x])
     37     {
     38         t1=f[x];
     39         f[x]=r;
     40         x=t1;
     41     }
     42     return r;
     43 }
     44 void uni(int x,int y)
     45 {
     46     int t1=find(x);
     47     int t2=find(y);
     48     if(t1==t2)//发现一个点和其所要连接的点在一个集合时,说明产生了环
     49     {
     50         int cnt1=0;
     51         int temp=x;
     52         do
     53         {
     54             root[x]=++cnt1;
     55             x=nxt[x];
     56         }while(!root[x]);
     57         x=temp;
     58         num[x]=cnt1;
     59         x=nxt[x];
     60         while(x!=temp)
     61         {
     62             num[x]=cnt1;
     63             x=nxt[x];
     64         }
     65     }
     66     else
     67     f[t1]=t2;
     68 }
     69 int dp[2*N][22];
     70 void makermq()
     71 {
     72     int i,j;
     73     for(i=1;i<ti;i++)
     74     dp[i][0]=deep[i];
     75     for(j=1;(1<<j)<ti;j++)
     76     {
     77         for(i=1;i+(1<<j)-1<ti;i++)
     78         dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
     79     }
     80 }
     81 int rmq(int s,int e)
     82 {
     83     int k=(int)(log((e-s+1)*1.0)/log(2.0));
     84     return min(dp[s][k],dp[e-(1<<k)+1][k]);
     85 }
     86 void init()
     87 {
     88     memset(dp,0x3f,sizeof(dp));
     89     memset(root,0,sizeof(root));
     90     memset(num,0,sizeof(num));
     91     memset(head,-1,sizeof(head));
     92     memset(used,0,sizeof(used));
     93     memset(deep,0,sizeof(deep));
     94     memset(fir,0,sizeof(fir));
     95     memset(father,0,sizeof(father));
     96     memset(list,0,sizeof(list));
     97     cnt=0;
     98     ti=1;
     99     int i;
    100     for(i=1;i<=n;i++)
    101     {
    102         f[i]=i;
    103     }
    104 }
    105 void dfs(int u,int d,int v)
    106 {
    107     used[u]=true;
    108     if(root[u])
    109     {
    110         d=1;
    111         v=u;
    112     }
    113     list[ti]=u;
    114     deep[ti]=d;
    115     fir[u]=ti;
    116     ti++;
    117     father[u]=v;
    118     int i;
    119     for(i=head[u];i>=0;i=edge[i].next)
    120     {
    121         if(!used[edge[i].v])
    122         {
    123             dfs(edge[i].v,d+1,v);
    124             list[ti]=u;
    125             deep[ti]=d;
    126             ti++;
    127         }
    128     }
    129 }
    130 int main()
    131 {
    132     int i,j,m,a,b,temp,t1,t2;
    133     while(scanf("%d%d",&n,&m)!=EOF)
    134     {
    135         init();
    136         for(i=1;i<=n;i++)
    137         {
    138             scanf("%d",&nxt[i]);
    139             add(nxt[i],i);
    140             uni(i,nxt[i]);
    141         }
    142         for(i=1;i<=n;i++)
    143         if(root[i]&&(!used[i]))
    144         dfs(i,1,i);
    145         makermq();
    146         for(i=1;i<=m;i++)
    147         {
    148             scanf("%d%d",&a,&b);
    149             if(find(a)!=find(b))
    150             {
    151                 printf("-1 -1\n");
    152                 continue;
    153             }
    154             if(father[a]==father[b])
    155             {
    156                 t1=a,t2=b;
    157                 if(fir[a]>fir[b])//这里要特别注意
    158                 {
    159                     t1=b,t2=a;
    160                 }
    161                 temp=rmq(fir[t1],fir[t2]);
    162                 printf("%d %d\n",deep[fir[a]]-temp,deep[fir[b]]-temp);
    163             }
    164             else
    165             {
    166                 temp=num[father[a]];
    167                 t1=deep[fir[a]]-1;
    168                 t2=deep[fir[b]]-1;
    169                 int fa=father[a];
    170                 int fb=father[b];
    171                 int ans1=t1,ans2=t2;
    172                 if(root[fa]<root[fb])
    173                 {
    174                     ans1+=(root[fb]-root[fa]);
    175                     ans2+=(root[fa]+num[fa]-root[fb]);
    176                 }
    177                 else
    178                 {
    179                     ans1+=(root[fb]+num[fb]-root[fa]);
    180                     ans2+=(root[fa]-root[fb]);
    181                 }
    182                 if(max(ans1,t2)<max(t1,ans2))
    183                 {
    184                     printf("%d %d\n",ans1,t2);
    185                 }
    186                 else if(max(ans1,t2)>max(t1,ans2))
    187                 {
    188                     printf("%d %d\n",t1,ans2);
    189                 }
    190                 else
    191                 {
    192                     if(min(ans1,t2)<min(t1,ans2))
    193                     {
    194                         printf("%d %d\n",ans1,t2);
    195                     }
    196                     else if(min(ans1,t2)>min(t1,ans2))
    197                     {
    198                         printf("%d %d\n",t1,ans2);
    199                     }
    200                     else
    201                     {
    202                         if(ans1>=t2)
    203                         {
    204                             printf("%d %d\n",ans1,t2);
    205                         }
    206                         else
    207                         {
    208                             printf("%d %d\n",t1,ans2);
    209                         }
    210                     }
    211                 }
    212             }
    213         }
    214     }
    215     return 0;
    216 }
  • 相关阅读:
    mvc 在ii7上发布时遇到的问题只解决
    @Html.Raw 显示Html的标签
    补发————grid布局
    补发————DOM与BOM
    web实验博客3.css-position
    web专业课学习及往后方向发展
    bom&dom
    网格代码
    简单用户注册表单
    自我介绍
  • 原文地址:https://www.cnblogs.com/caozhenhai/p/2697350.html
Copyright © 2011-2022 走看看