地址:http://codeforces.com/contest/1076/problem/D
因为di定义为是图上1到i点的最短路径的长度,如果不限制边数,那么最少需要就是n - 1条边,使得n个点用最短路径边连起来,迪杰斯特拉就是用已知最短路的点去更新其他点,那么其他点的最短路一定会经过已知最短路的点,题中要求留k条边good点最多,那肯定是最短路上的点,k是1,有两个good点,k为2,有三个good点,。。。。类推下去,k >= n - 1,有n个good点,所以只要用迪杰斯特拉跑一遍最短路找到路径上的边即可,只需找到前k个(k < n - 1) 或n - 1个边;
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int N = 3 * 1e5 + 5;
LL dis[N];
bool vis[N];
vector<pair<int,pair<int,int> > >ve[N];
typedef struct Node{
LL w;
int x,id;
friend bool operator < (const Node &p,const Node &q)
{
return p.w > q.w;
}
}Node;
priority_queue<Node>que;
vector<int>ans;
int main()
{
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
for(int i = 1;i <= m;++i){
int u,v,w;
scanf("%d %d %d",&u,&v,&w);
ve[u].pb(mp(w,mp(v,i)));
ve[v].pb(mp(w,mp(u,i)));
}
memset(dis,inf,sizeof(dis));
memset(vis,false,sizeof(vis));
dis[1] = 0;
que.push((Node){0,1,0});
while(!que.empty())
{
Node tmp = que.top();
que.pop();
if(vis[tmp.x]) continue;
vis[tmp.x] = true;
if(tmp.id) ans.pb(tmp.id);
if(ans.size() == n - 1 || ans.size() == k) break;
int len = ve[tmp.x].size();
for(int i = 0;i < len;++i){
int v = ve[tmp.x][i].se.fi;
int id = ve[tmp.x][i].se.se;
LL w = ve[tmp.x][i].fi;
if(!vis[v] && dis[tmp.x] + w < dis[v]){
dis[v] = dis[tmp.x] + w;
que.push((Node){dis[v],v,id});
}
}
}
printf("%d\n",ans.size());
for(int i = 0;i < ans.size();++i){
printf("%d ",ans[i]);
}
printf("\n");
return 0;
}