之江学院第0届校赛-H.qwb与学姐(最大生成树+lca)

来源:互联网 发布:win10网络允许 编辑:程序博客网 时间:2024/04/30 19:40

记录一个菜逼的成长。。

题目链接

一开始看到这题,想的是最大生成树+树链剖分+线段树。时间复杂度大概是O(mlogm+n+nlogn+klogn)
然而貌似是因为线段树的常数大然后炸了。。(不会zkw线段树,待学。orz

然后题解说的是最大生成树+倍增法lca
就是创建一个数组
dis[i][j]:=i2j
然后跟
anc数组一样处理就可以了。

#include <bits/stdc++.h>using namespace std;#define ALL(v) (v).begin(),(v).end()#define cl(a,b) memset(a,b,sizeof(a))#define clr clear()#define pb push_back#define mp make_pair#define fi first#define se second#define lson t<<1,l,mid#define rson t<<1|1,mid+1,rconst int INF = 0x3f3f3f3f;typedef long long LL;typedef pair<int,int> PII;const int maxe = 200000 + 10;const int maxn = 100000 + 10;struct Edge{    int to,next,w;}edge[maxn];int head[maxn],cnt;int deep[maxn],anc[maxn][20];int n,m;int dis[maxn][20];void add(int u,int v,int w){    edge[cnt].to = v;    edge[cnt].next = head[u];    edge[cnt].w = w;    head[u] = cnt++;}void init(){    cl(head,-1);    cl(deep,0);    cl(anc,-1);    cl(dis,INF);    cnt = 0;}void dfs(int u,int pre,int d){    deep[u] = d;    for( int i = head[u]; ~i; i = edge[i].next ){        int v = edge[i].to;        if(v == pre)continue;        anc[v][0] = u;        dis[v][0] = edge[i].w;        dfs(v,u,d+1);    }}void Init(){    for( int j = 1; (1<<j) <= n; j++ ){        for( int i = 1; i <= n; i++ ){            if(anc[i][j-1] != -1){                anc[i][j] = anc[anc[i][j-1]][j-1];                dis[i][j] = min(dis[i][j-1],dis[anc[i][j-1]][j-1]);            }        }    }}int lca(int a,int b){    int ret = INF;    int i,j;    if(deep[a] < deep[b])swap(a,b);    for( i = 0; (1<<i) <= deep[a]; i++ );    i--;    for( j = i; j >= 0; j-- ){        if(deep[a] - (1<<j) >= deep[b]){            ret = min(ret,dis[a][j]);            a = anc[a][j];        }    }    if(a == b)return ret;    for( j = i; j >= 0; j-- ){        if(anc[a][j] != -1 && anc[a][j] != anc[b][j]){            ret = min(ret,dis[a][j]);            ret = min(ret,dis[b][j]);            a = anc[a][j];            b = anc[b][j];        }    }    ret = min(ret,dis[a][0]);    ret = min(ret,dis[b][0]);    return ret;}int pre[maxn],ra[maxn];struct Bian{  int u,v,d;  Bian(){}  Bian(int uu,int vv,int dd){    u = uu;    v = vv;    d = dd;  }}bian[maxe];bool cmp(Bian a,Bian b){  return a.d > b.d;}int findr(int x){  return pre[x] == x ? pre[x] : pre[x] = findr(pre[x]);}void Kruskal(int n,int m){  for( int i = 1; i <= n; i++ )pre[i] = i;  sort(bian,bian+m,cmp);  for( int i = 0; i < m; i++ ){    int u = findr(bian[i].u),v = findr(bian[i].v);    if(u == v)continue;    pre[u] = v;    add(bian[i].u,bian[i].v,bian[i].d);    add(bian[i].v,bian[i].u,bian[i].d);  }}int main(){  int k;  while(~scanf("%d%d%d",&n,&m,&k)){    init();    for( int i = 0; i < m; i++ ){      scanf("%d%d%d",&bian[i].u,&bian[i].v,&bian[i].d);    }    Kruskal(n,m);    dfs(1,1,0);    Init();    while(k--){      int x,y;      scanf("%d%d",&x,&y);      printf("%d\n",lca(x,y));    }  }  return 0;}
阅读全文
0 0