• luogu 1967 货车运输


    题目大意:

    无向图上

    每次询问两个点

    寻找一条路径使这条路径上的最小值最大

    思路:

    先跑一个最大生成树

    然后在最大生成树上每次对每两个点跑一个lca

    在倍增的同时开一个数组a[i][j] 记录从i个点往上跑j条路里j条路中的最小值

    然后每次lca的时候顺便记录一下就行了

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<set>
      8 #include<map>
      9 #include<vector>
     10 #include<stack>
     11 #include<queue>
     12 #define ll long long
     13 #define inf 2147383611
     14 #define MAXN 10101
     15 using namespace std;
     16 inline int read()
     17 {
     18     int x=0,f=1;
     19     char ch;ch=getchar();
     20     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
     21     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
     22     return x*f;
     23 }
     24 struct data
     25 {
     26     int val,to,from;
     27     bool operator < (const data &a) const
     28     {
     29         return val>a.val;
     30     }
     31 }edge[MAXN*7];
     32 int cnt,n,m,T,to[MAXN*7],first[MAXN],nex[MAXN*7],val[MAXN*7];
     33 int depth[MAXN];
     34 int father[MAXN];
     35 int f[MAXN][20],ans[MAXN][20];
     36 int find(int x) {return x==father[x]?x:father[x]=find(father[x]);}
     37 bool ok(int a,int b)
     38 {
     39     int fa=find(a),fb=find(b);
     40     if(fa==fb) return 1;
     41     else {father[fb]=fa;return 0;}
     42 }
     43 void add(int u,int v,int a) {nex[++cnt]=first[u],first[u]=cnt,val[cnt]=a,to[cnt]=v;}
     44 void kruskal()
     45 {
     46     int tot=0;
     47     for(int i=1;i<=m;i++)
     48     {
     49         if(!ok(edge[i].from,edge[i].to)) {tot++;add(edge[i].from,edge[i].to,edge[i].val);add(edge[i].to,edge[i].from,edge[i].val);}
     50         if(tot==n-1) return ;
     51     }
     52 }
     53 void dfs(int x,int fa)
     54 {
     55     for(int i=1;i<=17;i++)
     56     {
     57         if((1<<i)>=depth[x]) break;
     58         ans[x][i]=min(ans[x][i-1],ans[f[x][i-1]][i-1]);
     59         f[x][i]=f[f[x][i-1]][i-1];
     60     }
     61     for(int i=first[x];i;i=nex[i]) if(to[i]!=fa) {depth[to[i]]=depth[x]+1,ans[to[i]][0]=val[i],f[to[i]][0]=x;dfs(to[i],x);}
     62 }
     63 int lca(int u,int v)
     64 {
     65     if(depth[u]<depth[v]) swap(u,v);
     66     int d=depth[u]-depth[v];
     67     for(int i=17;i>=0;i--)
     68         if(d&(1<<i)) u=f[u][i];
     69     for(int i=17;i>=0;i--)
     70     {
     71         if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
     72     }
     73     if(u==v) return v;
     74     return f[u][0];
     75 }
     76 int dis(int u,int v)
     77 {
     78     int res=inf;
     79     if(depth[u]<depth[v]) swap(u,v);
     80     int d=depth[u]-depth[v];
     81     for(int i=17;i>=0;i--)
     82     {
     83         if(d&(1<<i)) {res=min(res,ans[u][i]);u=f[u][i];}
     84     }
     85     return res;
     86 }
     87 int main()
     88 {
     89     n=read(),m=read();
     90     int a,b,c;
     91     for(int i=1;i<=n;i++) father[i]=i;
     92     for(int i=1;i<=m;i++) 
     93     {
     94         a=read(),b=read(),c=read();
     95         edge[i].val=c,edge[i].from=a,edge[i].to=b;
     96     }
     97     sort(edge+1,edge+m+1);
     98     kruskal();
     99     int l;
    100     depth[1]=1;dfs(1,0);
    101     T=read();
    102     while(T--)
    103     {
    104         a=read(),b=read();
    105         l=lca(a,b);
    106         if(find(a)!=find(b)) printf("-1
    ");
    107         else printf("%d
    ",min(dis(a,l),dis(b,l)));
    108     }
    109 }
    View Code

    倍增数组开小了调了好久

    两个倍增写串了调了好久

    我太菜了

  • 相关阅读:
    课程设计第十九天
    课程设计第十天八
    课程设计第十七天
    程序设计第十六天
    课程设计第十五天
    一个完整的大作业
    数据结构化与保存
    爬取新闻列表
    用requests库和BeautifulSoup4库爬取新闻列表
    中文词频统计及词云制作
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/7608705.html
Copyright © 2020-2023  润新知