• P1967 货车运输


    题目描述

    A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

    输入输出格式

    输入格式:

    输入文件名为 truck.in。

    输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道

    路。 接下来 m 行每行 3 个整数 x、 y、 z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意: x 不等于 y,两座城市之间可能有多条道路

    接下来一行有一个整数 q,表示有 q 辆货车需要运货。

    接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意: x 不等于 y

    输出格式:

    输出文件名为 truck.out。

    输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货

    车不能到达目的地,输出-1。

    输入输出样例

    输入样例#1:
    4 3
    1 2 4
    2 3 3
    3 1 1
    3
    1 3
    1 4
    1 3
    输出样例#1:
    3
    -1
    3

    说明

    对于 30%的数据,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000;

    对于 60%的数据,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000;

    对于 100%的数据,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。

    和这道题熬战总计7.5小时后终于调试出来了!!

    思路我就不多说了,跑一边最大树然后倍增求LCA不断取最小值就好

    我在这里说一下这道题容易犯的错误

    1.在读入第一个图的时候必须用有向边储存,但是跑最大生成树产生的图必须用无向图储存

    2.在选择源点的时候可以从1->n进行dfs,但是必须要开一个vis数组,单纯一个deep数组是不可以的

    3.在从低处点往高处点跳的时候判断条件一定是deep[s[x][i]]>=deep[y],必须是>=!!!

    4.在取最小值得时候一定是在更新变量之前取!!

    5.注意各种变量的初始化!

    因为调试时间比较长,所以代码可以比较长,但没什么高大上的语句,写的还算简单

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 const int MAXN=50001;
      8 int n,m;
      9 int x,y,z;
     10 int vis[MAXN];
     11 struct node
     12 {
     13     int u,v,w,next;
     14 }edge[MAXN],a[MAXN];
     15 int num=1;
     16 int head[MAXN];
     17 int f[MAXN];
     18 int anum=1;
     19 int ahead[MAXN];
     20 int deep[MAXN];
     21 int s[MAXN][20];
     22 int take[MAXN][20];
     23 void edge_add(int x,int y,int z)
     24 {
     25     edge[num].u=x;
     26     edge[num].v=y;
     27     edge[num].w=z;
     28     edge[num].next=head[x];
     29     head[x]=num++;
     30 }
     31 void a_add(int i)
     32 {
     33     a[anum].u=edge[i].u;
     34     a[anum].v=edge[i].v;
     35     a[anum].w=edge[i].w;
     36     a[anum].next=ahead[a[anum].u];
     37     ahead[a[anum].u]=anum++;
     38     a[anum].u=edge[i].v;
     39     a[anum].v=edge[i].u;
     40     a[anum].w=edge[i].w;
     41     a[anum].next=ahead[a[anum].u];
     42     ahead[a[anum].u]=anum++;
     43 }
     44 int comp(const node & a ,const node & b)
     45 {return a.w>b.w;}
     46 
     47 int find(int x)
     48 {
     49     if(f[x]!=x)
     50     f[x]=find(f[x]);
     51     return f[x];
     52 }
     53 void unionn(int x,int y)
     54 {
     55     int fx=find(x);
     56     int fy=find(y);
     57     f[fx]=fy;
     58 }
     59 void Biggest_Kruskal()
     60 {
     61     sort(edge+1,edge+num+1,comp);
     62     int k=0;
     63     for(int i=1;i<=num;i++)
     64     {
     65         int uu=edge[i].u;
     66         int vv=edge[i].v;
     67         if(find(uu)!=find(vv))
     68         { 
     69             a_add(i);
     70             unionn(uu,vv);
     71             k++;
     72         }
     73         if(k==n-1)break;
     74     }
     75     //for(int i=1;i<=anum;i++)
     76     //    cout<<a[i].u<<" "<<a[i].v<<" "<<a[i].w<<" "<<a[i].next<<endl;
     77 }
     78 void Build_Tree(int p)
     79 {
     80     vis[p]=1;
     81     for(int i=ahead[p];i!=-1;i=a[i].next)
     82     {
     83          int will=a[i].v;
     84         if(vis[will])continue;
     85         vis[will]=1;
     86        
     87             deep[will]=deep[p]+1;
     88             s[will][0]=p;
     89             take[will][0]=a[i].w;
     90             Build_Tree(will);
     91     }
     92 }
     93 void Initialize_Step()
     94 {
     95     for(int i=1;i<=18;i++)
     96     {
     97         for(int j=1;j<=n;j++)
     98         {
     99             s[j][i]=s[s[j][i-1]][i-1];
    100             take[j][i]=min(take[j][i-1],take[s[j][i-1]][i-1]);
    101         }
    102     }
    103 }
    104 int LCA(int x,int y)
    105 {
    106     int ans=0x7ffffff;
    107     if(deep[x]<deep[y])
    108     swap(x,y);
    109     for(int i=18;i>=0;i--)
    110     {
    111         if(s[x][i]!=0)
    112         if(deep[s[x][i]]>=deep[y])
    113         {
    114             ans=min(ans,take[x][i]);
    115             x=s[x][i];    
    116         }
    117     }
    118     if(x==y)
    119     return ans;
    120     for(int i=18;i>=0;i--)
    121     {
    122         if(s[x][i]!=s[y][i])
    123         {
    124             ans=min(ans,take[x][i]);
    125             ans=min(ans,take[y][i]);
    126             x=s[x][i];
    127             y=s[y][i];
    128         }
    129     }
    130     ans=min(ans,take[x][0]);
    131     ans=min(ans,take[y][0]);
    132     return ans;
    133 }
    134 int main()
    135 {
    136 //    memset(take,0xf,sizeof(take));
    137     scanf("%d%d",&n,&m);
    138     
    139     for(int i=1;i<=n;i++)
    140     {head[i]=-1;f[i]=i;ahead[i]=-1;}
    141     
    142     for(int i=1;i<=m;i++)
    143     {
    144         scanf("%d%d%d",&x,&y,&z);
    145         edge_add(x,y,z);
    146         //edge_add(y,x,z);
    147     }
    148     Biggest_Kruskal();
    149     //deep[1]=1;
    150     for(int i=1;i<=n;i++)
    151     {
    152         if(vis[i]==0)
    153         Build_Tree(i);
    154     }
    155     
    156     Initialize_Step();
    157     int q;
    158     scanf("%d",&q);
    159     for(int i=1;i<=q;i++)
    160     {
    161         int x,y;
    162         scanf("%d%d",&x,&y);
    163         if(find(x)!=find(y))
    164         {
    165             printf("-1
    ");
    166             continue;
    167         }
    168         printf("%d
    ",LCA(x,y));
    169     }
    170     return 0;
    171 }
  • 相关阅读:
    OpenCR 固件修复
    E-PUCK2机器人-固件更新
    E-puck2机器人系列教程-2.软件的安装与使用
    E-PUCK2机器人-硬件
    E-puck2机器人系列教程-固件修复升级
    GridView
    TimePicker 和TimePickerDiag
    android中实现简单的播放
    ListView的使用
    android的activity的跳转
  • 原文地址:https://www.cnblogs.com/zwfymqz/p/6836547.html
Copyright © 2020-2023  润新知