CodeForces - 828F Best Edge Weight

Best Edge Weight

 CodeForces - 828F 

题目大意:n个点和m条边,要求求每一条边的最大权值使得这条边出现在任意的生成树中。

解题思路:先做最小生成树求得任意的一个最小生成树。然后对于在生成树上的边和不在

生成树上的边分两种情况讨论。

·1.对于不在生成树上的边u-v,如果它想要出现在任意一个生成树中,它需要满足生成树上小于u-v的路径边权的最大值。

因为按照克鲁斯卡尔的思想,我们按照边权排序,我们只需要把在u,v节点联通之前把这条变加进去就可以了。

2。对于在生成树上的边u-v,如果u-v不想被别的边所替代,那么u-v必定是小于所有不在生成树上的边且经过u-v的边的最小边权。

以上两种方法设计到对两点之间路径上边权的查询。

可以用树链剖分,也可以用倍增。

值得注意的是,对于第二种处理,最后还有再求一次,相当于线段树的pushdown操作,很巧妙。

学到了倍增法查询两点之间路径的边权最小值。

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define sca(x) scanf("%d",&x)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fir first
#define sec second
#define inf 0x3f3f3f3f

const int N = 2e5+5;
struct node
{
    int x,y,w,id;
    friend bool operator <(node a,node b)
    {
        return a.w<b.w;
    }
};

vector<node>V;
vector<pair<int,int> >G[N];

int f[N],used[N];

int Find(int x)
{
    return f[x]==x?x:f[x]=Find(f[x]);
}

void make_tree(int n,int m)//先求得任意一个最小生成树
{
    for(int i=1;i<=n;i++)f[i]=i;
    sort(V.begin(),V.end());
    for(int i=0;i<m;i++)
    {
        int f1=Find(V[i].x);
        int f2=Find(V[i].y);
        if(f1!=f2)
        {
            f[f1]=f2;
            G[V[i].x].pb(mp(V[i].y,V[i].w));
            G[V[i].y].pb(mp(V[i].x,V[i].w));
            used[i]=1;
        }
    }
}

int b[N][20],a[N][20],c[N][20];
int ans[N],dep[N];

void dfs(int u,int fa)
{
    b[u][0]=fa;
    dep[u]=dep[fa]+1;
    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i].fir;
        int w=G[u][i].sec;
        if(v!=fa)
        {
            a[v][0]=w;//架空根节点,将边权转化为点权
            dfs(v,u);
        }
    }
}

void pre_work(int n)
{
    for(int i=1;i<=18;i++)
    {
        for(int j=1;j<=n;j++)
        {
            b[j][i]=b[b[j][i-1]][i-1];
            a[j][i]=max(a[j][i-1],a[b[j][i-1]][i-1]);
        }
    }
}

int query(int x,int y)
{
    int ans=0;
    if(dep[x]<dep[y])swap(x,y);
    for(int i=18;i>=0;i--)
    {
        if(dep[b[x][i]]>=dep[y])
        {
            ans=max(ans,a[x][i]);
            x=b[x][i];
        }
    }
    if(x==y)return ans;
    for(int i=18;i>=0;i--)
    {
        if(b[x][i]!=b[y][i])
        {
            ans=max(ans,max(a[x][i],a[y][i]));
            x=b[x][i];
            y=b[y][i];
        }
    }
    return max(ans,max(a[x][0],a[y][0]));
}

void upd(int x,int y,int val)
{
    if(dep[x]<dep[y])swap(x,y);
    for(int i=18;i>=0;i--)
    {
        if(dep[b[x][i]]>=dep[y])
        {
            c[x][i]=min(c[x][i],val);
            x=b[x][i];
        }
    }
    if(x==y)return ;
    for(int i=18;i>=0;i--)
    {
        if(b[x][i]!=b[y][i])
        {
            c[x][i]=min(c[x][i],val);
            c[y][i]=min(c[y][i],val);
            x=b[x][i];
            y=b[y][i];
        }
    }
    c[x][0]=min(c[x][0],val);//最后不要忘了更新。
    c[y][0]=min(c[y][0],val);
}

int main()
{
    int n,m;
    sca(n),sca(m);
    for(int i=1;i<=m;i++)
    {
        node tmp;
        scanf("%d%d%d",&tmp.x,&tmp.y,&tmp.w);
        tmp.id=i;
        V.pb(tmp);
    }
    make_tree(n,m);
    dfs(1,0);
    pre_work(n);
    memset(c,inf,sizeof(c));
    for(int i=0;i<m;i++)
    {
        if(!used[i])
        {
            ans[V[i].id]=query(V[i].x,V[i].y)-1;
            upd(V[i].x,V[i].y,V[i].w);
        }
    }
    for(int i=18;i>=1;i--)//由于上边的upd操作我们只更新了大区间,现在要下推。
    {
        for(int j=1;j<=n;j++)
        {
            c[j][i-1]=min(c[j][i-1],c[j][i]);
            c[b[j][i-1]][i-1]=min(c[b[j][i-1]][i-1],c[j][i]);
        }
    }
    for(int i=0;i<m;i++)
    {
        if(used[i])
        {
            int x=V[i].x;
            int y=V[i].y;
            if(b[x][0]==y) ans[V[i].id]=c[x][0]-1;
            else ans[V[i].id]=c[y][0]-1;
        }
    }
    for(int i=1;i<=m;i++)
    {
        if(ans[i]>=1000000001)printf("-1 ");
        else printf("%d ",ans[i]);
    }
    printf("\n");
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
点点多人视频空间是dd5588推出的集视频聊天、游戏、远程会议,互动娱乐与一体的大型综合娱乐平台。平台汇聚大量网络明星、歌手和美女主持,更带来互动交友和视频游戏功能,给所有的网友们带来网络K歌,飚歌,游戏,会议,交友的全新网络生活。   9.1版本更新说明:   1、新增数款休闲游戏。   2、更换音视频流解码,不降低音质,网络更通畅。   3、增加添加区长,副区长模块。   4、完整查询个人所有礼品流水,房间人气功能。   5、多麦序功能,掉线后自动恢复麦序。   6、增加座驾功能。   视频窗口可以运用各种虚拟视频的特效功能让呈现效果变得更加炫目。      双线互通让聊天畅通无阻二视频房间全部为双线互通,即网通电信互联互通,让用户体验沟通中的绝对“零”距离。   核心功能:   免费多方视频聊天娱乐免费高清晰全视频、全音频沟通,随时随地畅聊无限,可随时邀请好友进行点对点聊天或进入聊天室交流。   多人同时语音,网络party,声色共享,好友沟通绝对“零”距离,不被打扰的私密空间。   多人视频聊天室精彩不断,两路视频、语音,排麦及主持机制,优质的立体声音频效果,更有300人容量的视频群体娱乐大舞台。   最生动的虚拟礼物轻松点击即可赠送好友,传情达意尽享交友乐趣。   视频休闲游戏乐趣无穷点点聊天室客户端面板可直接点击进入游戏大厅登陆面板,多种棋牌娱乐游戏供您选择;可以视频语音的休闲游戏,体会面对面的游戏快感。   超级交友平台,让您即时体验粉红男女浪漫遭遇的感觉。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值