想拿一个NOIP题试试呢。。
拿到这道题以后,是个图论题很高兴的说!
给定一个无向图,要求无向图上任意两点u,v之间路径的最小值
读完题各种花哨:
网络流,SPFA,二分答案,树链剖分???
等等:树!
想一下,如果现在新加入一条边,如果这条边比u,v之间的路径上的最小权值还要小,那么这条边就木有用了是不是!
嗯。我们就要求一棵最大生成树!!
u,v询问怎么搞?。。额,这。。直接BFS?
还是要涨姿势的,套一下LCA模板吧!
结果因为构最大生成树的时候没有Add两次导致哇哩哇啦红一片。。
还有就是LCA模板不熟练
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 50010
using namespace std;
int cnt;
struct Edge{
int from,to,dis;
bool operator<(const Edge &k)const{return dis>k.dis;}
}e[maxn*2];
void add(int u,int v,int dis){
cnt++;e[cnt].from=u;e[cnt].to=v;e[cnt].dis=dis;
}
int n,m;
int fa[maxn];
int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);}
struct EDGE{
int next,to,dis;
}edge[maxn];
int h[maxn],num;
void Add(Edge& k){
++num;int u=k.from;
edge[num].to=k.to;
edge[num].next=h[u];
edge[num].dis=k.dis;
h[u]=num;
}
int F[maxn],dep[maxn];
int anc[10010][14],ancmin[10010][14];
void dfs_buildtree(int u,int fa){
F[u]=fa;
if(fa>0)dep[u]=dep[fa]+1;
for(int i=h[u];i;i=edge[i].next){
int v=edge[i].to;
if(v!=fa){
ancmin[v][0]=edge[i].dis;
dfs_buildtree(v,u);
}
}return;
}
void Kruscal(){
sort(e+1,e+1+cnt);
for(int i=1;i<=cnt;i++){
int u=getfa(e[i].from),v=getfa(e[i].to);
if(u!=v){fa[v]=u;Add(e[i]);swap(e[i].from,e[i].to);Add(e[i]);}
}
cnt=0;
memset(ancmin,127,sizeof ancmin);
for(int i=1;i<=n;i++){
fa[i]=getfa(fa[i]);
if(fa[i]==i)dfs_buildtree(i,-1);
}
}
void GET_LCA(){
memset(anc,-1,sizeof anc);
for(int i=1;i<=n;i++)anc[i][0]=F[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i<=n;i++){
int a=anc[i][j-1];
if(a!=-1){
anc[i][j]=anc[a][j-1];
ancmin[i][j]=min(ancmin[a][j-1],ancmin[i][j-1]);
}
}
}
int ASK_LCA(int p,int q){
if(getfa(p)!=getfa(q))return -1;
int log,i,ans=0x7ffffff;
if(dep[p]<dep[q])swap(p,q);
for(log=1;(1<<log)<=dep[p];log++);log--;
for(i=log;i>=0;i--)
if(dep[p]-(1<<i)>=dep[q]){
ans=min(ans,ancmin[p][i]);
p=anc[p][i];
}
if(p==q)return ans;
for(i=log;i>=0;i--)//LCA不要越界QAQ~
if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){
ans=min(ans,ancmin[p][i]);p=anc[p][i];
ans=min(ans,ancmin[q][i]);q=anc[q][i];
}
ans=min(ans,ancmin[p][0]);ans=min(ans,ancmin[q][0]);
return ans;
}
int main(){
freopen("truck.in","r",stdin);
freopen("truck.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)fa[i]=i;
int u,v,d;
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&d);
add(u,v,d);//add(v,u,d);
}
Kruscal();
GET_LCA();
int Q;
scanf("%d",&Q);
for(int i=1;i<=Q;i++){
scanf("%d%d",&u,&v);
printf("%d\n",ASK_LCA(u,v));
}
return 0;
}