3287 货车运输

3287 货车运输

 

2013年NOIP全国联赛提高组

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
 
 
题目描述 Description

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

输入描述 Input Description

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

输出描述 Output Description

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

样例输入 Sample Input

4 3 
1 2 4 
2 3 3 
3 1 1 
3
1 3 
1 4 
1 3

样例输出 Sample Output

3
-1
3

数据范围及提示 Data Size & Hint

对于 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。

 
 

20分代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 5001
int g[N][N];
int n,m,q;
int main(){
    
    scanf("%d%d",&n,&m);
    memset(g,-1,sizeof g);
    for(int i=1;i<=m;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        g[x][y]=max(g[x][y],z);
        g[y][x]=max(g[y][x],z);
    }
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(i!=j&&g[i][k]!=-1&&g[k][j]!=-1){
                    g[i][j]=max(g[i][j],min(g[i][k],g[k][j]));
                }
            }
        }
    }
    scanf("%d",&q);
    for(int i=1;i<=q;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d
",g[x][y]);
    }
    return 0;
}

朴素LCA的AC代码:

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 10010
int n,m,q,fa[N],fv[N],vi[N],s[N][51],v[N][51];
struct node{
    int x,y,s;
}a[N*5];
inline bool cmp(const node &q,const node &p){
    return q.s>p.s;
}
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void dfs(int x){
    for(int i=1;i<=s[x][0];i++){
        if(fa[s[x][i]]==s[x][i]){
            fa[s[x][i]]=x;
            fv[s[x][i]]=v[x][i];
            dfs(s[x][i]);
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].s);
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++){
        int fx=find(a[i].x),fy=find(a[i].y);
        if(fx!=fy){
            fa[fx]=fy;
            s[a[i].x][++s[a[i].x][0]]=a[i].y;
            s[a[i].y][++s[a[i].y][0]]=a[i].x;
            v[a[i].x][++v[a[i].x][0]]=a[i].s;
            v[a[i].y][++v[a[i].y][0]]=a[i].s;
        }
    }
    for(int i=1;i<=n;i++) fa[i]=i;
    fa[1]=0;
    dfs(1);
    scanf("%d",&q);
    for(int i=1,x,y;i<=q;i++){
        scanf("%d%d",&x,&y);
        for(int j=1;j<=n;j++) vi[j]=1e8;
        for(int j=x;vi[fa[j]]==1e8&&j;j=fa[j])
            vi[fa[j]]=min(vi[j],fv[j]);
        int tmp=1e8;
        for(int j=y;;j=fa[j]){
            if(vi[j]<1e8||j==x){
                tmp=min(tmp,vi[j]);break;
            }
            tmp=min(tmp,fv[j]);
            if(fa[j]==j||!j){tmp=-1;break;}
        }
        if(!tmp) tmp=-1;
        printf("%d
",tmp);
    }
    return 0;
}

倍增LCA就是快!

AC代码:

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define N 10100
inline const int read(){
    register int x=0,f=1;
    register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
int n,m,q,fa[N],dep[N],f[N][21],g[N][21];
struct node{
    int u,v,w;
    bool operator < (const node &t) const {return w>t.w;}
}e[N<<1];
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
vector<int>p[N],c[N];
void dfs(int x,int de){
    for(int i=0;i<p[x].size();i++){
        if(!dep[p[x][i]]){
            dep[p[x][i]]=de+1;
            f[p[x][i]][0]=x;
            g[p[x][i]][0]=c[x][i];
            dfs(p[x][i],de+1);
        }
    }
}
int lca(int a,int b){
    if(dep[a]<dep[b]) swap(a,b);
    int t=dep[a]-dep[b];
    int ans=0x7fffffff;
    for(int i=0;i<=20;i++){
        if((1<<i)&t){
            ans=min(ans,g[a][i]);
            a=f[a][i];
        }
    }
    if(a==b) return ans;
    for(int i=20;i>=0;i--){
        if(f[a][i]!=f[b][i]){
            ans=min(ans,g[a][i]);
            ans=min(ans,g[b][i]);
            a=f[a][i];
            b=f[b][i];
        }
    }
    return min(ans,min(g[a][0],g[b][0]));
}
int main(){
    n=read();m=read();
    for(int i=1;i<=m;i++) e[i].u=read(),e[i].v=read(),e[i].w=read();
    for(int i=1;i<=n;i++) fa[i]=i;
    stable_sort(e+1,e+m+1);
    for(int i=1;i<=m;i++){
        int fx=find(e[i].u),fy=find(e[i].v);
        if(fx!=fy){
            fa[fx]=fy;
            p[e[i].u].push_back(e[i].v);
            p[e[i].v].push_back(e[i].u);
            c[e[i].u].push_back(e[i].w);
            c[e[i].v].push_back(e[i].w);
        }
    }
    dep[1]=1;
    dfs(1,1);
    for(int j=1;j<=20;j++){
        for(int i=1;i<=n;i++){
            f[i][j]=f[f[i][j-1]][j-1];
            g[i][j]=min(g[i][j-1],g[f[i][j-1]][j-1]);
        }
    }
    q=read();
    for(int i=1,x,y,tmp;i<=q;i++){
        x=read();y=read();
        if(find(x)!=find(y)){puts("-1");continue;}
        printf("%d
",lca(x,y));
    }
    return 0;
}

 2017-04-06

/最小值最大:最大生成树找最小边 
#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
const int N=1e4+5;
const int M=1e5+5;
int n,m,Q,fa[N],dep[N],f[N][20],g[N][20];
struct data{int u,v,w;}a[M];
struct edge{int v,w,next;}e[M];int tot,head[N];
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
bool operator <(const data &a,const data &b){
    return a.w>b.w;
}
int find(int x){
    return fa[x]==x?x:fa[x]=find(fa[x]);
}
void add(int x,int y,int z){
    e[++tot].v=y;e[tot].w=z;e[tot].next=head[x];head[x]=tot;
    e[++tot].v=x;e[tot].w=z;e[tot].next=head[y];head[y]=tot;
}
void dfs(int x){
    for(int i=head[x];i;i=e[i].next){
        if(!dep[e[i].v]){
            dep[e[i].v]=dep[x]+1;
            f[e[i].v][0]=x;
            g[e[i].v][0]=e[i].w;
            dfs(e[i].v);
        }
    }
}
int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    int t=dep[x]-dep[y],ans=2e9;
    for(int i=0;i<=18;i++){
        if(t&(1<<i)){
            ans=min(ans,g[x][i]);
            x=f[x][i];
        }
    }
    if(x==y) return ans;
    for(int i=18;~i;i--){
        if(f[x][i]!=f[y][i]){
            ans=min(ans,g[x][i]);
            ans=min(ans,g[y][i]);
            x=f[x][i];
            y=f[y][i];
        }
    }
    return min(ans,min(g[x][0],g[y][0]));
}
int main(){
    freopen("truck.in","r",stdin);
    freopen("truck.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++) a[i].u=read(),a[i].v=read(),a[i].w=read();
    sort(a+1,a+m+1);
    for(int i=1,k=0,x,y,fx,fy;i<=m;i++){
        x=a[i].u,y=a[i].v;
        fx=find(x);fy=find(y);
        if(fx!=fy){
            fa[fx]=fy;
            add(x,y,a[i].w);
            if(++k==n-1) break;
        }
    }
    dep[1]=1;dfs(1);
    for(int j=1;j<=18;j++){
        for(int i=1;i<=n;i++){
            f[i][j]=f[f[i][j-1]][j-1];
            g[i][j]=min(g[i][j-1],g[f[i][j-1]][j-1]);
        }
    }
    Q=read();
    for(int i=1,x,y;i<=Q;i++){
        x=read();y=read();
        if(find(x)!=find(y)) puts("-1");
        else printf("%d
",lca(x,y));
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shenben/p/5635712.html