[2017纪中11-9]玩游戏 最短路数+LCA

来源:互联网 发布:ubuntu samba用户名 编辑:程序博客网 时间:2024/06/11 03:57

题面
考虑这样定义的最短路对应的最短路树恰好是最小生成树。因为add操作不多,每次暴力重构最短路树,询问的时候跑lca即可。复杂度O(n^2logn)。
代码:

#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#define ll long longusing namespace std;int n,m,K,Q,fa[5010],d[5010],f[5010][15];ll g[5010][15];struct edge{    int t;ll w;    edge *next;}*con[5010];void ins(int x,int y,ll w){    edge *p=new edge;    p->t=y;    p->w=w;    p->next=con[x];    con[x]=p;}struct node{    int x,y;ll w;}e[110000],z[5010];bool cmp(node a,node b){return a.w<b.w;}int getfa(int v){    if(fa[v]==v) return v;    fa[v]=getfa(fa[v]);    return fa[v];}bool merge(int x,int y){    if(getfa(x)!=getfa(y)) {fa[fa[x]]=y;return 1;}    return 0;}void MST(int &m){    for(int i=1;i<=n;i++)        fa[i]=i;    sort(e+1,e+m+1,cmp);    int cnt=0;    for(int i=1;i<=m;i++)    {        if(merge(e[i].x,e[i].y)) z[++cnt]=e[i];        if(cnt==n-1) break;    }    for(int i=1;i<n;i++)        e[i]=z[i];    m=n-1;  }void dfs(int v){    d[v]=d[f[v][0]]+1;    for(edge *p=con[v];p;p=p->next)        if(p->t!=f[v][0])        {            f[p->t][0]=v;            g[p->t][0]=p->w;            dfs(p->t);         }}void pre(){    for(int k=1;(1<<k)<=n;k++)        for(int i=1;i<=n;i++)            f[i][k]=f[f[i][k-1]][k-1],g[i][k]=max(g[i][k-1],g[f[i][k-1]][k-1]);}ll qry(int x,int y){    ll re=0;    if(d[x]<d[y]) swap(x,y);    for(int k=14;k>=0;k--) if(d[f[x][k]]>=d[y]) re=max(re,g[x][k]),x=f[x][k];    if(x==y) return re;    for(int k=14;k>=0;k--) if(f[x][k]!=f[y][k]) re=max(re,max(g[x][k],g[y][k])),x=f[x][k],y=f[y][k];    return max(re,max(g[x][0],g[y][0]));}int main(){    scanf("%d%d%d",&n,&m,&K);    for(int i=1;i<=m;i++)        scanf("%d%d%lld",&e[i].x,&e[i].y,&e[i].w);    scanf("%d",&Q);    bool mi=1;    while(Q--)    {        char opt[6];int x,y;scanf("%s",opt);        if(opt[0]=='g')        {            if(mi)            {                MST(m);                for(int i=1;i<=n;i++)con[i]=NULL;                memset(f,0,sizeof(f));                memset(g,0,sizeof(g));                memset(d,0,sizeof(d));                for(int i=1;i<=m;i++)                    ins(e[i].x,e[i].y,e[i].w),ins(e[i].y,e[i].x,e[i].w);                dfs(1);                pre();                mi=0;            }            ll ans=0;            for(int i=1;i<=K;i++)            {                scanf("%d%d",&x,&y);                ans^=qry(x,y);            }            if(ans==0) puts("Baozika");            else puts("madoka");        }        else {m++;mi=1;scanf("%d%d%lld",&e[m].x,&e[m].y,&e[m].w);}    }    return 0;}