概述
传送门
题 意 : 给 定 一 张 无 向 图 , 问 最 多 保 留 k 条 边 , 使 得 有 1 到 其 余 点 题意:给定一张无向图,问最多保留k条边,使得有1到其余点 题意:给定一张无向图,问最多保留k条边,使得有1到其余点
的 最 短 路 不 变 的 点 数 最 多 。 的最短路不变的点数最多。 的最短路不变的点数最多。
分
析
:
最
短
路
径
树
,
很
明
显
,
当
k
≥
n
−
1
时
,
我
们
只
需
要
保
分析:最短路径树,很明显,当{k}geq{n-1}时,我们只需要保
分析:最短路径树,很明显,当k≥n−1时,我们只需要保
留
最
短
路
径
上
的
边
即
可
留最短路径上的边即可
留最短路径上的边即可
当 k ≤ n − 1 时 , 需 要 删 除 最 短 路 径 树 上 的 一 些 边 当kleq{n-1}时,需要删除最短路径树上的一些边 当k≤n−1时,需要删除最短路径树上的一些边
且 这 些 边 为 最 深 层 的 边 且这些边为最深层的边 且这些边为最深层的边
在 跑 最 短 路 的 同 时 利 用 p r e 记 录 每 个 点 的 前 驱 , 然 后 重 新 建 出 在跑最短路的同时利用pre记录每个点的前驱,然后重新建出 在跑最短路的同时利用pre记录每个点的前驱,然后重新建出
最 短 路 径 树 , 最 后 b f s 记 录 边 即 可 最短路径树,最后bfs记录边即可 最短路径树,最后bfs记录边即可
c o d e : code: code:
#include <set>
#include <map>
#include <list>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <bitset>
#include <vector>
#include<cstring>
#include <stdio.h>
#include <iomanip>
#include <iostream>
#include <algorithm>
using namespace std;
#define endl "n"
#define ll long long
#define Mp make_pair
#define INF 0x3f3f3f3f
#define Pair pair<int,int>
typedef unsigned long long ull;
#define IO ios::sync_with_stdio(false);
const int N = 2e6+5;
const int maxn = 3e5+5;
#define int long long
vector<Pair>e[maxn];
int pre[maxn];
int dis[maxn],vis[maxn];
void Dij(int s)
{
memset(dis,INF,sizeof dis);
priority_queue<Pair,vector<Pair>,greater<Pair>>q;
q.push({0,s});
dis[s]=0;
while(!q.empty())
{
int x=q.top().second; q.pop();
if(vis[x]) continue; vis[x]=true;
for(auto v:e[x])
{
int y=v.first,w=v.second;
if(dis[y]>dis[x]+w){
dis[y]=dis[x]+w;
pre[y]=x;
if(!vis[y]) q.push({dis[y],y});
}
}
}
}
int n,m,k;
bool use[maxn];
vector<int>ee[N],ans;
map<int,map<int,int>>mp,p;
void dfs(int x)
{
int y=pre[x];
if(y==-1||p[x][y]==1) return;
p[x][y]=p[y][x]=1;
ee[y].push_back(x);
dfs(y);
}
void bfs(int s)
{
int cnt=0;
queue<int>q; q.push(s);
while (!q.empty())
{
int x=q.front(); q.pop();
for(auto y:ee[x])
{
if(cnt<k&&!use[mp[x][y]])
ans.push_back(mp[x][y]),use[mp[x][y]]=true,cnt++;
if(cnt==k) break;
q.push(y);
}
if(cnt==k) break;
}
cout<<ans.size()<<endl;
for(auto id:ans) cout<<id<<" ";
cout<<endl;
}
void solve()
{
cin>>n>>m>>k;
memset(pre,-1,sizeof pre);
k=min(k,n-1);
for(int i=1;i<=m;i++){
int u,v,w; cin>>u>>v>>w;
e[u].push_back({v,w});
e[v].push_back({u,w});
mp[u][v]=i;
mp[v][u]=i;
}
Dij(1);
for(int i=1;i<=n;i++) dfs(i);
bfs(1);
}
signed main()
{
//
freopen("5.in","r",stdin);
//
freopen("5.out","w",stdout);
IO;
//
int T;cin>>T; while (T--)
solve();
return 0;
}
最后
以上就是单薄苗条为你收集整理的D. Edge Deletion的全部内容,希望文章能够帮你解决D. Edge Deletion所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复