codevs 1519 过路费

这个和货车运输没有区别。。。只不过换成了最小生成树。

#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],ma[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;
ma[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("0\n");
else
{
int r=lca(x,y);
int maxx=0;
if (x!=r)
{
for (int i=15;i>=0;i--)
{
if ((dis[anc[x][i]]>=dis[r]) && (anc[x][i]!=0))
{
maxx=max(maxx,ma[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))
{
maxx=max(maxx,ma[y][i]);
y=anc[y][i];
}
}
}
if (maxx==0) printf("0\n");
else printf("%d\n",maxx);
}
}
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];
ma[i][e]=max(ma[anc[i][e-1]][e-1],ma[i][e-1]);
}
scanf("%d",&q);
for (int i=1;i<=q;i++)
work();
return 0;
}

时间: 2024-10-25 19:07:17

codevs 1519 过路费的相关文章

codevs 1519 过路费 最小生成树+倍增

/*codevs 1519 过路费 最小生成树+倍增*/ #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 100010 #define inf 0x3f3f3f3 using namespace std; int n,m,q,num,head[maxn],fa[maxn][25],mx[maxn][25],c[maxn],father

习题:codevs 1519 过路费

今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这个kruskal选边建图的过程. 1 struct kruskalsolve{ 2 int l,r,w; 3 }kr[maxm];此处省略的内容接下来会有给出全部代码 4 int find(int x){ 5 if(f[x] != x)f[x] = find(f[x]); 6 return f[x]

1519 过路费

1519 过路费 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 大师 Master 题解 题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值.如:A到B长度为 2,B到C 长度为3,那么开车从 A经过 B到C 需要上交的过路费为 3.    佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个

[ CodeVS冲杯之路 ] P2492

不充钱,你怎么AC? 题目:http://codevs.cn/problem/2492/ 在此先orz小胖子,教我怎么路径压缩链表,那么这样就可以在任意节点跳进链表啦(手动@LCF) 对于查询操作,直接树状数组(以下简称BIT)维护,修改操作就一个个暴力开方搞,再用差值单点更新BIT 不过这样会TLE,要加一点优化对不对,正如开头所说的路径压缩链表 路径压缩链表其实就是个并查集,在普通的链表里,删去两个连续的节点后会是下面这种情况,如删去2,3 当访问 2 的时候,会跳到3,但 3 已经删除了,

习题:过路费(kruskal+并查集+LCA)

过路费  [问题描述]在某个遥远的国家里,有 n 个城市.编号为 1,2,3,…,n.这个国家的政府修 建了 m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市 T 需 要收取的过路费为所经过城市之间道路长度的最大值.如:A 到 B 长度为 2,B 到 C 长度为 3,那么开车从 A 经过 B 到 C 需要上交的过路费为 3. 佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个城市,因此 他需要频繁地上交过路费,由于忙于做生意,所以他无时间来寻找交过路费最低 的行驶路线.然

[CODEVS 1281] Xn数列

描述 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn http://codevs.cn/problem/1281/ 分析 比较裸的矩阵乘法题, 好久没做了, 写写思路 假设矩阵 A = { {a1, a2}, {a3, a4} }, B = { {b1, b2}, {b3, b4} }. 根据矩阵乘法的计算方法, 有 : A×B = { {a1b1+a2b2, a1b2+a2b4}, {a3b1+a4b3, a3b2+a4b4} }. 那

Codevs 1257 打砖块

1257 打砖块 http://codevs.cn/problem/1257/ 题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有一块砖.第i层的砖块从左至右编号为1,2,……i,第i层的第j块砖有一个价值a[i,j](a[i,j]<=50).下面是一个有5层砖块的例子.如果你要敲掉第i层的第j块砖的话,若i=1,你可以直接敲掉它,若i>1,则你必须先敲掉第i-1层的第j和第j+1块砖. 你的任务是从一个有n(n<=5

codevs——T1219 骑士游历

 http://codevs.cn/problem/1219/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个

1683 车厢重组 codevs

http://codevs.cn/problem/1683/ 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题目描述 Description 在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转.一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序.于是他就负责用这座桥将进站的车厢按车厢号从小到大排列.他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序