题意:
给定n个点,m条边的无向连通图,定义d[j]为1号结点到j结点的最短距离
让你删去一些边,让边数剩余最多为k条,如果删边前后的两个图中d[j]相同的话,那j结点就是good点,
给定的边编号1~m,现在让你给出一种删边方案,是的good点尽量多;
思路:
单原点最短路,我们知道剩下的边数e,最大是min(n-1, k);
其实不用管剩余多少条边,按照dijkstra求最短路的过程,把前面访问到的e条边放进答案里就是了;因为这样访问到的边连接的点就是原图中的最短路,现在选出来也是最短路;
#include<bits/stdc++.h>
using namespace std;
#define out fflush(stdout);
#define fast ios::sync_with_stdio(0),cin.tie(0);
#define FI first
#define SE second
typedef long long ll;
typedef pair<ll,ll> P;
const int maxn = 3e5 + 7;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;
ll n, m, k;
ll u, v, c;
struct no {
ll u, c, id;
};
vector<no> vec[maxn];
struct node {
ll d, v, id;
bool operator< (const node &a) const {
return (d > a.d);
}
};
priority_queue<node> qu;
bool vis[maxn];
set<ll> ans;
int main() {
scanf("%lld%lld%lld", &n, &m, &k);
for(int i = 1; i <= m; ++i) {
scanf("%lld%lld%lld", &u, &v, &c);
vec[u].push_back(no{v, c, i});
vec[v].push_back(no{u, c, i});
}
for(auto i : vec[1]) {
qu.push(node{i.c, i.u, i.id});
}
vis[1] = 1;
int anss = k;
while(1) {
if(qu.empty()) break;
node t = qu.top(); qu.pop();
ll u = t.v, d = t.d, id = t.id;
if(vis[u]) continue;
vis[u] = 1;
if(k) {
k--;
ans.insert(id);
}
for(auto i : vec[u]) {
if(vis[i.u]) continue;
qu.push(node{d+i.c, i.u, i.id});
}
}
cout << ans.size() << endl;
int t = 0;
for(auto i : ans) {
t++;
printf("%lld", i);
if(t == ans.size()) break;
printf(" ");
}
return 0;
}