[CF160D]Edges in MST (最小生成树+LCA+差分)

待填坑

Code

//CF160D Edges in MST
//Apr,4th,2018
//树上差分+LCA+MST
#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
long long read()
{
    long long x=0,f=1; char c=getchar();
    while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
const int N=100000+1000;
struct line
{
    int s,t,w1,w,ans,no;
}e[N];
struct edge
{
    int t,w,no;
};
bool cmp(line a,line b)
{
    return a.w1<b.w1;
}
bool cmp2(line a,line b)
{
    return a.no<b.no;
}
vector <edge> r[N];
struct mrk
{
    int num,count;
};
vector <mrk> mk[N];
int n,m;
bool IsOnMST[N];
int fa[N][21],mx[N][21],d[N],mark[N];
bool visited[N];
void dfs(int now,int depth)
{
    visited[now]=true;
    d[now]=depth;
    for(int i=1;i<=20;i++)
    {
        fa[now][i]=fa[fa[now][i-1]][i-1];
        mx[now][i]=max(mx[now][i-1],mx[fa[now][i-1]][i-1]);
    }
    int to=r[now].size();
    for(int i=0;i<to;i++)
        if(visited[r[now][i].t]==false)
        {
            fa[r[now][i].t][0]=now;
            mx[r[now][i].t][0]=r[now][i].w;
            dfs(r[now][i].t,depth+1);
        }
}
int LCA(int x,int y,int &MAX)
{
    if(d[x]<d[y])
        swap(x,y);
    for(int i=20;i>=0;i--)
        if(d[fa[x][i]]>=d[y])
        {
            MAX=max(MAX,mx[x][i]);
            x=fa[x][i];
        }
    if(x==y) return x;
    for(int i=20;i>=0;i--)
        if(fa[x][i]!=fa[y][i])
        {
            MAX=max(MAX,mx[x][i]);
            MAX=max(MAX,mx[y][i]);
            x=fa[x][i],y=fa[y][i];
        }
    MAX=max(MAX,mx[x][0]);
    MAX=max(MAX,mx[y][0]);
    return fa[x][0];
}
int FA[N];
inline int FindFather(int x)
{
    if(FA[x]==0) return x;
    return FA[x]=FindFather(FA[x]);
}
void MST()
{
    sort(e+1,e+1+m,cmp);
    for(int i=1;i<=m;i++)
        if(e[i].w1!=e[i-1].w1)
            e[i].w=e[i-1].w+1;
        else
            e[i].w=e[i-1].w;
    int tot=0;
     for(int i=1;i<=m;i++)
    {
        int f1=FindFather(e[i].s),f2=FindFather(e[i].t);
        if(f1!=f2)
        {
            FA[f1]=f2;
            r[e[i].s].push_back((edge){e[i].t,e[i].w,i});
            r[e[i].t].push_back((edge){e[i].s,e[i].w,i});
            IsOnMST[i]=true;
            tot++;
            e[i].ans=2;
        }
        if(tot==n-1)
            break;
    }
}
void dfs2(int now)
{
    visited[now]=true;
    for(int i=0;i<int(r[now].size());i++)
        if(visited[r[now][i].t]==false)
        {
            int stm=mark[r[now][i].w];
            dfs2(r[now][i].t);
            if(mark[r[now][i].w]-stm>0)
                e[r[now][i].no].ans=1;
        }
    for(int i=0;i<int(mk[now].size());i++)
        mark[mk[now][i].num]+=mk[now][i].count;
}
int main()
{
    n=read(),m=read();
    for(int i=1;i<=n;i++)
        mk[i].reserve(4),
        r[i].reserve(4);
    for(int i=1;i<=m;i++)
        e[i].s=read(),e[i].t=read(),e[i].w1=read(),e[i].no=i;
    
    MST();
    dfs(1,1);
    
    for(int i=1;i<=m;i++)
        if(IsOnMST[i]==false)
        {
            int MAX=0,lca=LCA(e[i].s,e[i].t,MAX);
            if(MAX==e[i].w) 
            {
                e[i].ans=1;
                mk[e[i].s].push_back((mrk){MAX,1});
                mk[e[i].t].push_back((mrk){MAX,1});
                mk[lca].push_back((mrk){MAX,-2});
            }
        }
        
    memset(visited,0,sizeof visited);
    dfs2(1);
        
    sort(e+1,e+1+m,cmp2);
    for(int i=1;i<=m;i++)
        if(e[i].ans==0)
            printf("none
");
        else if(e[i].ans==1)
            printf("at least one
");
        else
            printf("any
");
    return 0;
}
C++
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。
原文地址:https://www.cnblogs.com/GoldenPotato/p/8746852.html