• [NOIp2013] 货车运输


    比较水的一道题,之前做过类似的,今天没事儿干,写了这个......

    洛谷 P1967 传送门

    算法很显然了,先求个生成树,在树上跑倍增......

    有两个地方被卡了,一个是并查集忘赋初值了,还有就是倍增的时候应该先更新ans,再更新x,我写反了。

    如果先更新x,g[x][i]就不是原来那个g[x][i]了,ans也就不对了。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 
      6 int n,m,q;
      7 int hd[10005],to[20005],lim[20005],nx[20005],ec;
      8 int ff[10005];
      9 
     10 int findfa(int p)
     11 {
     12     if(ff[p]==p)return p;
     13     ff[p]=findfa(ff[p]);
     14     return ff[p];
     15 }
     16 
     17 struct edge
     18 {
     19     int ea,eb,elim;
     20 }e[50005];
     21 
     22 int cmp(edge q,edge w)
     23 {
     24     return q.elim>w.elim;
     25 }
     26 
     27 void addedge(int af,int at,int al)
     28 {
     29     to[++ec]=at;
     30     lim[ec]=al;
     31     nx[ec]=hd[af];
     32     hd[af]=ec;
     33 }
     34 
     35 int d[10005],f[10005][20],g[10005][20];
     36 
     37 void dfs(int p,int fa,int lm)
     38 {
     39     f[p][0]=fa;
     40     g[p][0]=lm;
     41     d[p]=d[fa]+1;
     42     for(int i=hd[p];i;i=nx[i])
     43     {
     44         if(to[i]!=fa)dfs(to[i],p,lim[i]);
     45     }
     46 }
     47 
     48 int ask(int x,int y)
     49 {
     50     int ans=0x3f3f3f3f;
     51     if(d[x]<d[y])swap(x,y);
     52     for(int i=18;i>=0;i--)
     53         if(d[f[x][i]]>=d[y])
     54             ans=min(ans,g[x][i]),x=f[x][i];
     55     if(x==y)return ans;
     56     for(int i=18;i>=0;i--)
     57         if(f[x][i]!=f[y][i])
     58             ans=min(ans,min(g[x][i],g[y][i])),x=f[x][i],y=f[y][i];
     59     ans=min(ans,min(g[x][0],g[y][0]));
     60     return ans;
     61 }
     62 
     63 int main()
     64 {
     65     scanf("%d%d",&n,&m);
     66     for(int i=1;i<=m;i++)
     67     {
     68         scanf("%d%d%d",&e[i].ea,&e[i].eb,&e[i].elim);
     69     }
     70     sort(e+1,e+1+m,cmp);
     71     for(int i=1;i<=n;i++)ff[i]=i;
     72     for(int i=1;i<=m;i++)
     73     {
     74         int fa=findfa(e[i].ea),fb=findfa(e[i].eb);
     75         if(fa==fb)continue;
     76         ff[fa]=fb;
     77         addedge(e[i].ea,e[i].eb,e[i].elim);
     78         addedge(e[i].eb,e[i].ea,e[i].elim);
     79     }
     80     memset(g,0x3f,sizeof(g));
     81     for(int i=1;i<=n;i++)
     82     {
     83         if(!d[i])dfs(i,0,0x3f3f3f3f);
     84     }
     85     for(int i=1;i<=18;i++)
     86     {
     87         for(int j=1;j<=n;j++)
     88         {
     89             f[j][i]=f[f[j][i-1]][i-1];
     90             g[j][i]=min(g[j][i-1],g[f[j][i-1]][i-1]);
     91         }
     92     }
     93     scanf("%d",&q);
     94     for(int i=1;i<=q;i++)
     95     {
     96         int x,y;
     97         scanf("%d%d",&x,&y);
     98         int fx=findfa(x),fy=findfa(y);
     99         if(fx!=fy)printf("-1
    ");
    100         else printf("%d
    ",ask(x,y));
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    我的浏览器收藏夹分类
    我的浏览器收藏夹分类
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 318 最大单词长度乘积
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 316 去除重复字母
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
    Java实现 LeetCode 315 计算右侧小于当前元素的个数
  • 原文地址:https://www.cnblogs.com/cervusy/p/9740766.html
Copyright © 2020-2023  润新知