http://codeforces.com/contest/1076/problem/D
题意:
给你一张图,起点为1,让你最多保留k条边,使得1到点i的最短路长度di【不变】的个数最多。
POINT:
想一想就知道,每加一条边,就可以使一个点的最短路保持不变。
所以这题就是选k条边,可以让k个点的最短路不变。
具体就是跑一个最短路。
每当确定一个点的最短路的时候,即vis[u]=1的时候,把到u的这条边加进去就行了。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define LL long long
vector<LL> ans;
const LL N = 3e5+55;
vector<LL>G[N];
vector<LL>L[N];
vector<LL>P[N];
LL dis[N];
LL vis[N];
LL n,m,k;
struct node
{
LL u;
LL pre;
LL dis;
node(LL uu,LL pp,LL dd)
{
u=uu;pre=pp;dis=dd;
}
bool friend operator < (node a,node b)
{
return a.dis>b.dis;
}
};
priority_queue<node>q;
void dij()
{
for(LL i=1;i<=n;i++)
dis[i]=1LL*3e5*1e9+123123123LL;;
dis[1]=0;
q.push(node(1,-1,0));
while(!q.empty()){
node uu=q.top();
q.pop();
LL u=uu.u;
if(vis[u]) {
continue;
}
vis[u]=1;
ans.push_back(uu.pre);
if((LL)ans.size()==k+1) break;
for(LL j=0;j<G[u].size();j++){
LL v=G[u][j];
if(dis[v]>dis[u]+L[u][j]){
dis[v]=dis[u]+L[u][j];
q.push(node(v,P[u][j],dis[v]));
}
}
}
}
int f[N];
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
for(LL i=1;i<=m;i++){
LL u,v,x;
scanf("%lld%lld%lld",&u,&v,&x);
G[u].push_back(v);G[v].push_back(u);
P[u].push_back(i);P[v].push_back(i);
L[u].push_back(x);L[v].push_back(x);
}
dij();
for(int i=1;i<ans.size();i++){
f[ans[i]]=1;
}
int num=0;
for(int i=1;i<=m;i++){
if(f[i]) num++;
}
printf("%d\n",num);
for(int i=1;i<=m;i++){
if(f[i]) printf("%d ",i);
}
}