codevs 3287 货车运输

由于有m条边,考虑建一颗最大生成树,然后LCA求解问题。这题也是神TM多细节。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxv 40005
#define maxe 200005
#define maxq 30005
using namespace std;
int n,m,x,y,z,anc[maxv][20],mi[maxv][20],father[maxv],g[maxv],h[maxv];
int nume=0,numt=0,q;
bool vis[maxv],judge[maxv];
int dis[maxv];
struct edge
{
int u,v,w,nxt;
}e[maxe],tr[maxe];
void addedge(int u,int v,int w)
{
e[++nume].u=u;
e[nume].v=v;
e[nume].w=w;
e[nume].nxt=g[u];
g[u]=nume;
}
void addtree(int u,int v,int w)
{
tr[++numt].u=u;
tr[numt].v=v;
tr[numt].w=w;
tr[numt].nxt=h[u];
h[u]=numt;
}
bool cmp(edge x,edge y)
{
return x.w>y.w;
}
int getfather(int x)
{
if (x!=father[x])
father[x]=getfather(father[x]);
return father[x];
}
void unionn(int x,int y)
{
int r1=getfather(x),r2=getfather(y);
father[r1]=r2;
}
void kruskal()
{
for (int i=1;i<=n;i++)
father[i]=i;
for (int i=1;i<=nume*2;i++)
{
int u=e[i].u,v=e[i].v;
if (getfather(u)!=getfather(v))
{
addtree(u,v,e[i].w);
addtree(v,u,e[i].w);
unionn(u,v);
judge[u]=true;
judge[v]=true;
}
}
}
void dfs(int u)
{
vis[u]=true;
for (int i=h[u];i;i=tr[i].nxt)
{
int v=tr[i].v;
if (vis[v]==false)
{
dis[v]=dis[u]+1;
anc[v][0]=u;
mi[v][0]=tr[i].w;
dfs(v);
}
}
}
int lca(int x,int y)
{
if (dis[x]>dis[y]) swap(x,y);
for (int i=15;i>=0;i--)
{
if ((dis[anc[y][i]]>=dis[x]) && (anc[y][i]!=0))
y=anc[y][i];
}
for (int i=15;i>=0;i--)
{
if (anc[x][i]!=anc[y][i])
{
x=anc[x][i];
y=anc[y][i];
}
}
if (x==y) return x;
else return anc[x][0];
}
void work()
{
scanf("%d%d",&x,&y);
if ((judge[x]==false) || (judge[y]==false) || getfather(x)!=getfather(y))
printf("-1\n");
else
{
int r=lca(x,y);
int minn=99999999;
if (x!=r)
{
for (int i=15;i>=0;i--)
{
if ((dis[anc[x][i]]>=dis[r]) && (anc[x][i]!=0))
{
minn=min(minn,mi[x][i]);
x=anc[x][i];
}
}
}
if (y!=r)
{
for (int i=15;i>=0;i--)
{
if ((dis[anc[y][i]]>=dis[r]) && (anc[y][i]!=0))
{
minn=min(minn,mi[y][i]);
y=anc[y][i];
}
}
}
if (minn==99999999) printf("-1\n");
else printf("%d\n",minn);
}
}
int main()
{
memset(g,0,sizeof(g));
memset(h,0,sizeof(h));
memset(vis,false,sizeof(vis));
memset(dis,0,sizeof(dis));
memset(judge,false,sizeof(judge));
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
addedge(x,y,z);
addedge(y,x,z);
}
sort(e+1,e+2*m+1,cmp);
kruskal();
dfs(1);
for (int e=1;e<=15;e++)
for (int i=1;i<=n;i++)
{
anc[i][e]=anc[anc[i][e-1]][e-1];
mi[i][e]=min(mi[anc[i][e-1]][e-1],mi[i][e-1]);
}
scanf("%d",&q);
for (int i=1;i<=q;i++)
work();
return 0;
}

时间: 2024-12-11 23:45:10

codevs 3287 货车运输的相关文章

3287 货车运输 2013年NOIP全国联赛提高组 40 分

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和

3287 货车运输

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城

AC日记——货车运输 codevs

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A

C++之路进阶——LCA(货车运输)

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和

Codevs3278[NOIP2013]货车运输

3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题目描述 Description A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入描述 Input Description 第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和

货车运输

版权声明:本文为博主原创文章,未经博主允许不得转载. 传送门:货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个

洛谷P1967 [NOIP2013提高组Day1T2]货车运输

P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y

倍增LCA NOIP2013 货车运输

货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条

poj1330|bzoj3732|noip2013 货车运输 kruskal+倍增lca

学了一早上倍增,感觉lca还是tarjan好写. poj1330 1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #include <algorithm> 5 #define DEG 20//2^20 6 #define maxn 10010 7 using namespace std; 8 struct node 9 { 10 int v, next; 11 }a[maxn*2