Code[vs]3287【NOIP2013提高组】【7.13考试第四题】货车运输

来源:互联网 发布:网络电视不更新怎么办 编辑:程序博客网 时间:2024/04/27 20:34

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

【输入格式】
  第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道路。
接下来 m 行每行 3 个整数 x、y、z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z 的道路。注意:x 不等于 y,两座城市之间可能有多条道路。
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来 q 行,每行两个整数 x、y,之间用一个空格隔开,表示一辆货车需要从 x 城市运输货物到 y 城市,注意:x 不等于 y。

【输出格式】
  输出共有 q 行,每行一个整数,表示对于每一辆货车,它的最大载重是多少。如果货车不能到达目的地,输出-1。

【输入输出样例】

4 31 2 42 3 33 1 131 31 41 33-13

【数据范围】
对于 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。

做到了一道原题(该不会错了吧)这里写图片描述
如题,题目显然给出了一张边带权的无向图,所求是求从一个点x出发到y的路径,要求路径上的边权最小值最大。
面对这类型问题,有两种思路,一个是二分答案,另一个是贪心思想,而二分答案显然是对于每一个询问,都要用一次并查集的,对于询问多的情况就很慢,故利用kruskal预生成最优生成树,然后再用LCA找最小值。
其实做这个题的时候我差点忘记从那个点开始BFS了,想了半天。
做这种综合题一定要知道你数组的含义。

#include<cstdio>#include<iostream>#include<queue>#include<cstring>#include<algorithm>#include<vector>#define maxn 10005#define maxm 50005#define oo 100010using namespace std;int n,m,q;struct edge{    int u,v,w;};vector<edge>E;vector<int>g[maxn],w[maxn];int dist[maxn],dep[maxn],fa[maxn],pa[maxn];int used[maxm];bool cmp(edge a,edge b){    return a.w>b.w;}void initial(){    for(int i=1;i<=n;i++)pa[i]=i;}int find(int x){    return pa[x] = pa[x]==x? x:find(pa[x]);}void Union(int x,int y){    pa[find(x)]=find(y);}bool judge(int x,int y){    return find(x)==find(y);}void kruskal(){    initial();    sort(E.begin(),E.end(),cmp);    int cnt=0;    for(int i=0;i<E.size();i++)    {        int a=E[i].u,b=E[i].v,c=E[i].w;        if(judge(a,b))continue;        Union(a,b);        used[a]=1;        used[b]=1;        g[a].push_back(b);        w[a].push_back(c);        g[b].push_back(a);        w[b].push_back(c);        cnt++;        if(cnt==n-1)break;    }}void BFS(int s){    queue<int>q;    q.push(s);    fa[s]=s;    dist[s]=0;    dep[s]=1;    while(!q.empty())    {        int i=q.front();q.pop();        for(int k=0;k<g[i].size();k++)        {            int j=g[i][k],c=w[i][k];            if(fa[i]==j)continue;            fa[j]=i;            dist[j]=dist[i]+c;            dep[j]=dep[i]+1;            q.push(j);        }    }}int LCA(int x,int y){    int ans=oo;    if(dep[x]<dep[y])swap(x,y);    while(dep[x]!=dep[y])    {        ans=min(ans,(dist[x]-dist[fa[x]])),x=fa[x];    }    while(x!=y)    {        ans=min(ans,dist[x]-dist[fa[x]]),x=fa[x];        ans=min(ans,dist[y]-dist[fa[y]]),y=fa[y];    }    return ans;}int main(){    freopen("bus.in","r",stdin);    freopen("bus.out","w",stdout);    scanf("%d%d",&n,&m);    for(int i=1;i<=m;i++)    {        int x,y,z;        scanf("%d%d%d",&x,&y,&z);        E.push_back((edge){x,y,z});    }    kruskal();    int s;    for(int i=1;i<=n;i++)if(used[i])//找源点    {        s=i;break;    }    BFS(s)//以最优生成树上任意一点为根BFS生成dist、dep等数组    scanf("%d",&q);    for(int i=1;i<=q;i++)    {        int sx,sy;        scanf("%d%d",&sx,&sy);        if(used[sx]&&used[sy])        {            int ans=LCA(sx,sy);            printf("%d\n",ans);        }        else printf("-1\n");    }    return 0;}
1 0
原创粉丝点击