真nm简单。。
算法1:
发现其实所有的经过的边都是最小生成树上面的边,跑出最小生成树在上面求LCA即可。
算法2:
考虑从小到枚举每一个加入的边,直到组成最小生成树,没加一条边就判断所有的询问是否连通。
然后我们发现这个算法有点卡,于是我们可以进行优化:
1、开一个beg,beg前的全部枚举过就不用枚举了。
2、记录每一个点被加入最小生成树的时间,然后询问按照这个时间从小到大排序,每当找到一个询问中有点不在最小生成树里面就可以退出枚举。
然后就可以过了awa
#include<bits/stdc++.h>
using namespace std;
const int M=100005;
const int N=10005;
int n,m,cnt=0,k=0,first[M<<1],nxt[M<<1],fa[N],f[N][25],dis[N][25],dep[N];
struct node{
int u,v;
int w;
}a[M<<1],e[M<<1];
int cmp(node A,node B){
return A.w<B.w;
}
void add(int u,int v,int w){
e[++cnt].u=u;e[cnt].v=v;e[cnt].w=w;
nxt[cnt]=first[u];first[u]=cnt;
}
int find(int x){
if(x==fa[x]) return x;
else return fa[x]=find(fa[x]);
}
void unionn(int x,int y){
fa[x]=y;
}
void kruskal(){
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++){
int f1=find(a[i].u);
int f2=find(a[i].v);
if(f1!=f2){
unionn(f1,f2);
add(a[i].u,a[i].v,a[i].w);
add(a[i].v,a[i].u,a[i].w);
k++;
}
if(k==n-1) break;
}
}
void dfs(int u){
for(int i=1;(1<<i)<=dep[u];i++){
f[u][i]=f[f[u][i-1]][i-1];
dis[u][i]=max(dis[f[u][i-1]][i-1],dis[u][i-1]);
}
for(int i=first[u];i;i=nxt[i]){
int v=e[i].v;
if(!dep[v]){
dep[v]=dep[u]+1;
f[v][0]=u;
dis[v][0]=e[i].w;
dfs(v);
}
}
}
int LCA(int a,int b){
if(dep[a]<dep[b]) swap(a,b);
int t=dep[a]-dep[b];
for(int i=0;(1<<i)<=t;i++)
if(t&(1<<i)) a=f[a][i];
if(a==b) return a;
for(int j=19;j>=0;j--){
if(f[a][j]!=f[b][j])
a=f[a][j],b=f[b][j];
}
return f[a][0];
}
int query(int u,int v){
int t=dep[u]-dep[v],ans=0;
for(int i=0;(1<<i)<=t;i++)
if(t&(1<<i)){
ans=max(ans,dis[u][i]);
u=f[u][i];
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
}
sort(a+1,a+1+m,cmp);
kruskal();
dep[1]=1;
dfs(1);
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
int u,v;
scanf("%d%d",&u,&v);
int mid=LCA(u,v);
printf("%d\n",max(query(u,mid),query(v,mid)));
}
return 0;
}
算法1如上
还有算法2:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define orz cout<<"lyakioi!!!!!!!!!!!!!!!!!"<<endl
inline int r(){int s=0,k=1;char c=getchar();while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}while(isdigit(c)){s=s*10+c-'0';c=getchar();}return s*k;}
int n,m,q,fa[1000001],beg,times,b[1000001],used[1000001];
struct node
{
int from,to,dis;
}a[1000001];
struct ask
{
int from,to,bh,ans;
}t[1000001];
bool cmp(node x,node y)
{
return x.dis<y.dis;
}
bool pmc(ask x,ask y)
{
return max(b[x.from],b[x.to])<max(b[y.from],b[y.to]);
}
bool mcp(ask x,ask y)
{
return x.bh<y.bh;
}
int father(int x)
{
if(fa[x]!=x)fa[x]=father(fa[x]);
return fa[x];
}
int main()
{
beg=1;
n=r();m=r();
memset(b,0x3f,sizeof(b));
for(int i=1;i<=m;i++)
{
a[i].from=r();
a[i].to=r();
a[i].dis=r();
}
q=r();
for(int i=1;i<=q;i++)
{
t[i].from=r();
t[i].to=r();
t[i].bh=i;
}
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++)
{
int x=a[i].from,y=a[i].to;
if((b[x]>1e9)||(b[y]>1e9))
{
times++;
b[x]=min(b[x],times);
b[y]=min(b[y],times);
}
}
sort(t+1,t+q+1,pmc);
// for(int i=1;i<=)
for(int i=1;i<=n;i++)fa[i]=i;
for(int i=1;i<=m;i++)
{
int x=a[i].from,y=a[i].to;
used[x]=used[y]=1;
int fax=father(x),fay=father(y);
if(fax!=fay)
{
fa[fax]=fay;
for(int j=beg;j<=q;j++)
{
if(t[j].ans)continue;
x=t[j].from,y=t[j].to;
if(!used[x]||!used[y])break;
fax=father(x),fay=father(y);
if(fax==fay)t[j].ans=a[i].dis;
while(t[beg].ans)beg++;
}
}
}
sort(t+1,t+q+1,mcp);
for(int i=1;i<=q;i++)cout<<t[i].ans<<endl;
}