[洛谷 P1967]货车运输
转载请注明出处:http://danihao123.is-programmer.com/
倍增LCA经典题……
这题的做法就是求最大生成树,然后用倍增LCA法求瓶颈路……
注意一下,两点不连通时输出-1(其实这个用并查集判断不就行了……)!!!
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=10001,maxm=50001,maxlogn=15;
int n,m;
// edgeStruct
struct Edge{
int u,v,d;
friend bool operator < (const Edge& a,const Edge& b){
return a.d>b.d;
}
};
Edge EdgePool[maxm];
// Graph
vector<Edge> edges;
vector<int> G[maxn];
inline void Add_Edge(int x,int y,int c){
edges.push_back((Edge){x,y,c});
edges.push_back((Edge){y,x,c});
int m=edges.size();
G[x].push_back(m-2);
G[y].push_back(m-1);
}
// DJ Set
int p[maxn],rank[maxn];
int find_set(int x){
if(p[x]==x)
return x;
else
return p[x]=find_set(p[x]);
}
void link_set(int x,int y){
if(rank[x]>rank[y]){
p[y]=x;
}else{
p[x]=y;
if(rank[x]==rank[y])
rank[y]++;
}
}
inline void union_set(int x,int y){
link_set(find_set(x),find_set(y));
}
inline bool is_same(int x,int y){
return find_set(x)==find_set(y);
}
inline void init_dj_set(){
register int i;
for(i=1;i<=n;i++)
p[i]=i;
}
// MST
inline void mst(){
register int i,k=0;
sort(EdgePool,EdgePool+m);
init_dj_set();
for(i=0;i<m;i++){
Edge& e=EdgePool[i];
if(!is_same(e.u,e.v)){
Add_Edge(e.u,e.v,e.d);
union_set(e.u,e.v);
k++;
if(k==(n-1))
break;
}
}
}
// DFS & LCA
int dep[maxn],par[maxn][maxlogn],mincost[maxn][maxlogn];
void dfs(int x,int depth,int fa){
int i;
dep[x]=depth;
par[x][0]=fa;
for(i=0;i<G[x].size();i++){
Edge& e=edges[G[x][i]];
if(e.v!=fa){
mincost[e.v][0]=e.d;
dfs(e.v,depth+1,x);
}
}
}
inline void init_LCA(){
register int i,j,anc;
for(j=1;(1<<j)<=n;j++)
for(i=1;i<=n;i++)
if(par[i][j-1]!=-1){
anc=par[i][j-1];
par[i][j]=par[anc][j-1];
mincost[i][j]=min(mincost[i][j-1],mincost[anc][j-1]);
}
}
int query(int x,int y){
register int j,log,ans=0x4fffffff;
if(dep[x]<dep[y])
swap(x,y);
for(log=1;(1<<log)<=dep[x];log++);
log--;
for(j=log;j>=0;j--)
if((dep[x]-(1<<j))>=dep[y]){
ans=min(ans,mincost[x][j]);
x=par[x][j];
}
if(x==y)
return ans;
for(j=log;j>=0;j--)
if(par[x][j]!=-1 && par[x][j]!=par[y][j]){
ans=min(ans,mincost[x][j]);
ans=min(ans,mincost[y][j]);
x=par[x][j];
y=par[y][j];
}
ans=min(ans,min(mincost[x][0],mincost[y][0]));
return ans;
}
int main(){
register int i;
int a,b,c,q;
scanf("%d%d",&n,&m);
for(i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
EdgePool[i].u=a;
EdgePool[i].v=b;
EdgePool[i].d=c;
}
memset(par,-1,sizeof(par));
mst();
dfs(1,1,0);
init_LCA();
scanf("%d",&q);
while(q--){
scanf("%d%d",&a,&b);
if(is_same(a,b)){
printf("%d\n",query(a,b));
}else{
puts("-1");
}
}
return 0;
}
评论 (0)