思路来源
马石页老师&&张舟亢学长
题意
给你一个n点m边的原图,要求只保留这个图的k条边,
使子图上的最短路点尽可能多。
最短路点是指到1号节点的最短距离,在原图和子图的值相同。
要求输出子图边的编号,按加入的顺序对边进行编号1-m。
题解
模拟dijkstra的入堆过程,
由于dijkstra的贪心选点思想,每次一定选的是到顶点最近的点。
因此,必有一次松弛操作,使得一条边贡献出一个最短路点。
因此,开一个存结构体的优先队列,
我们只要一松弛,就把贡献松弛的边的id塞进优先队列里,
取出优先队列顶的点的时候(已按距离从小到大排序)
查一下是从哪个id的边使这个点成为到顶点的最短距离点(即当前被贪心选中的点),
然后把这个id加到ans里,满足k条return即可。
心得
最短路题变种好多啊QAQ
稍微考点概念就不会了GG
这题没开ll会被hack掉,
CF榜上hack率惊人QAQ
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=3e5+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pli pair<ll,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int head[maxn],cnt,n,m,k;
bool vis[maxn];
ll dis[maxn];
struct edge{int to,nex,id;ll w;}e[maxn<<1];
struct node
{
ll w;
int id,v;
node(ll a,int b,int c):w(a),id(b),v(c){
}
};
bool operator>(node a,node b)
{
return a.w>b.w;
}
priority_queue<node,vector<node>,greater<node> >q;
vector<int>ans;
void init()
{
rep(i,0,n-1)dis[i]=1e18;
cnt=0;
mem(head,-1);
}
void add(int u,int v,ll w)
{
e[cnt].to=v;
e[cnt].w=w;
e[cnt].id=cnt/2;
e[cnt].nex=head[u];
head[u]=cnt++;
}
void dijkstra(int s)
{
q.push(node(0,-1,s));//说明从哪条边转移到这点的
dis[s]=0;
while(!q.empty())
{
node tmp=q.top();
q.pop();
ll w=tmp.w;
int id=tmp.id,v=tmp.v;
if(vis[v]||w>dis[v])continue;
vis[v]=1;
if(id!=-1)ans.push_back(id);
if(ans.size()==k)return;
for(int i=head[v];~i;i=e[i].nex)
{
int to=e[i].to,id=e[i].id;
ll w=e[i].w;
if(dis[to]>dis[v]+w)
{
dis[to]=dis[v]+w;
q.push(node(dis[to],id,to));
}
}
}
}
int main()
{
sci(n),sci(m),sci(k);
init();
rep(i,0,m-1)
{
int u,v;
ll w;
sci(u),sci(v),scll(w);
u--,v--;
add(u,v,w);
add(v,u,w);
}
dijkstra(0);
int len=ans.size();
printf("%d\n",len);
if(len)
{
printf("%d",1+ans[0]);
rep(i,1,len-1)
printf(" %d",1+ans[i]);
puts("");
}
return 0;
}