1. 程式人生 > >P1967 貨車運輸

P1967 貨車運輸

題目 turn 貨車運輸 技術分享 bool print 最大生成樹 include none

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。

思路:

  LCA+最大生成樹(路的限重越大越好)

上代碼:

1.

技術分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 1000000000 #define MAXM 50010 #define MAXN 10010 struct node { int x,y,v; } E[MAXM]; struct node2 { int y,next,v; } e[MAXN*2]; int n,m,q,len; int vis[MAXN],f[MAXN],Link[MAXN],deep[MAXN],anc[MAXN][25],w[MAXN][25]; 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 cmp(node a,node b) { return a.v>b.v; } int find(int x) { return f[x]==x?x:f[x]=find(f[x]); } void insert(int x,int y,int v) { e[++len].next=Link[x]; Link[x]=len; e[len].y=y; e[len].v=v; } void dfs(int x) { //計算深度 vis[x]=1; for(int i=1; i<=20; i++) { anc[x][i]=anc[anc[x][i-1]][i-1]; w[x][i]=min(w[x][i-1],w[anc[x][i-1]][i-1]); } for(int i=Link[x]; i; i=e[i].next) if(!vis[e[i].y]) { deep[e[i].y]=deep[x]+1; anc[e[i].y][0]=x; w[e[i].y][0]=e[i].v; dfs(e[i].y); } } int lca(int x,int y) { //求LCA if(deep[x]<deep[y]) swap(x,y); for(int i=20; i>=0; i--) if(deep[anc[x][i]]>=deep[y]) x=anc[x][i]; if(x==y) return x; for(int i=20; i>=0; i--) if(anc[x][i]!=anc[y][i]) x=anc[x][i],y=anc[y][i]; return anc[x][0]; } int ask(int x,int f) { //求路徑上的最小值 int mn=INF; int t=deep[x]-deep[f]; for(int i=0; i<=16; i++) if(t&(1<<i)) { //1<<i一定為真,所以要求t為真 mn=min(mn,w[x][i]); x=anc[x][i]; } return mn; } int main() { memset(w,127/3,sizeof(w)); n=read(); m=read(); for(int i=1; i<=m; i++) { E[i].x=read(); E[i].y=read(); E[i].v=read(); } sort(E+1,E+m+1,cmp); for(int i=1; i<=n; i++) f[i]=i; for(int i=1; i<=m; i++) { int x=find(E[i].x),y=find(E[i].y); if(x!=y) { f[x]=y; insert(E[i].x,E[i].y,E[i].v); insert(E[i].y,E[i].x,E[i].v); } } for(int i=1; i<=n; i++) if(!vis[i]) dfs(i); q=read(); for(int i=1; i<=q; i++) { int x=read(),y=read(); if(find(x)!=find(y)) { printf("-1\n"); continue; } int t=lca(x,y); printf("%d\n",min(ask(x,t),ask(y,t))); } return 0; }
貨車運輸1

2.

技術分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define maxn 10010
#define maxm 50010

int n,m,f[maxn][20],sum[maxn][20],fa[maxn],num,p,dep[maxn],head[maxn];
bool vis[maxn];
struct node {
    int f,to,v;
} a[maxm];
struct Edge {
    int pre,v,to;
} e[maxm];

int cmp(node x,node y) {
    return x.v>y.v;
}

int find(int x) {
    if(fa[x]==x)return fa[x];
    else return fa[x]=find(fa[x]);
}

int connect(int x,int y) {
    int f1=find(x),f2=find(y);
    if(f1==f2)return 0;
    else fa[f1]=f2;
    return 1;
}

void Insert(int from,int to,int v) {
    e[++num].v=v;
    e[num].to=to;
    e[num].pre=head[from];
    head[from]=num;
}

void dfs(int now,int father,int deep) {
    vis[now]=1;
    dep[now]=deep;
    for(int i=head[now]; i; i=e[i].pre) {
        int v=e[i].to;
        if(v==father)continue;
        f[v][0]=now;
        sum[v][0]=e[i].v;
        dfs(v,now,deep+1);
    }
}

int lca(int x,int y) {
    if(x==y)return 0;
    int ans=0x3f3f3f3f;
    if(dep[x]<dep[y])swap(x,y);
    for(int i=18; i>=0; i--) {
        if(dep[f[x][i]]>=dep[y]&&f[x][i]!=0)
        ans=min(ans,sum[x][i]),x=f[x][i];
    }
    if(x==y)return ans;
    for(int i=18; i>=0; i--) {
        if(f[x][i]!=f[y][i]) {
            ans=min(ans,sum[x][i]);
            ans=min(ans,sum[y][i]);
            x=f[x][i];
            y=f[y][i];
        }
    }
    ans=min(sum[x][0],ans);
    ans=min(sum[y][0],ans);
    return ans;
}

int main() {
    memset(sum,127/3,sizeof(sum));
    int x,y,z;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++)scanf("%d%d%d",&a[i].f,&a[i].to,&a[i].v);
    for(int i=1; i<=n; i++)fa[i]=i;
    sort(a+1,a+m+1,cmp);
    int cnt=0;
    for(int i=1; i<=m; i++) {
        if(connect(a[i].f,a[i].to)) {
            Insert(a[i].f,a[i].to,a[i].v);
            Insert(a[i].to,a[i].f,a[i].v);
            cnt++;
            if(cnt==n-1)break;
        }
    }
    for(int i=1; i<=n; i++)if(!vis[i])dfs(i,0,1);
    for(int j=1; (1<<j)<=n; j++)
        for(int i=1; i<=n; i++)
            if(f[f[i][j-1]][j-1]!=0) {
                f[i][j]=f[f[i][j-1]][j-1];
                sum[i][j]=min(sum[i][j-1],sum[f[i][j-1]][j-1]);
            }
    scanf("%d",&p);
    for(int i=1; i<=p; i++) {
        scanf("%d%d",&x,&y);
        if(find(x)!=find(y)) {
            printf("-1\n");
            continue;
        }
        printf("%d\n",lca(x,y));
    }
}
貨車運輸2

自己選的路,跪著也要走完!!!

P1967 貨車運輸