Edge Deletion [contest/1076 D]

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/z591826160/article/details/84029306

Edge Deletion [contest/1076 D]

题面

在这里插入图片描述

思路

有一个很神奇的东西,我的队友之前在没有学过的情况下就写出来了(tql),叫灭绝树。
大概的性质是删除一个点,其子树都会灭绝
而这个灭绝树用在最短路上也有类似的性质,利用最短路算法保存松弛的前向结点即可构建灭绝树。
而本题就是在灭绝树上选择连续的k条边即可

代码

vector<pii>G[maxn];
vector<int>g[maxn],ans;
map<pii,int>id;
ll dis[maxn];
int fa[maxn];
bool in[maxn];
int n,m,k;
queue<int>Q;
void dij(){
    rep(i,0,n+1) 
        dis[i]=linf;
    in[1]=true;
    dis[1]=0;
    Q.push(1);
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        in[u]=false;
        rep(i,0,G[u].size()){
            int v=G[u][i].fi;
            ll  w=G[u][i].se;
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                fa[v]=u;
                if(!in[v])
                    Q.push(v);
                in[v]=true;
            }
        }
    }
}
int main(){
    rd(n,m,k);
    rep(i,0,m){
        int a,b,c;
        rd(a,b,c);
        G[a].pb(mp(b,c));
        G[b].pb(mp(a,c));
        id[mp(a,b)]=id[mp(b,a)]=i+1;
    }
    dij();
    rep(i,1,n+1)
        g[fa[i]].pb(i);
    while(!Q.empty())Q.pop();
    Q.push(1);
    while(!Q.empty()&&k){
        int u = Q.front();Q.pop();
        rep(i,0,g[u].size()){
            int v=g[u][i];
            if(v==fa[v])continue;
            ans.pb(id[mp(u,v)]);
            k--;
            Q.push(v);
            if(!k)break;
        }
    }
    printf("%d\n",ans.size());
    rep(i,0,ans.size())
        printf("%d ",ans[i]);
}

猜你喜欢

转载自blog.csdn.net/z591826160/article/details/84029306