版权声明:本文为博主原创文章,未经博主允许不得转载。 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]);
}