这个题倒是不难,但是我当时对于题目的理解导致写出来很复杂,所以记一下踩的坑。其实就是最短路树的应用,我的想法是先删掉不在树上的边,然后对于树上的边先删除连叶子的边,以此类推。这样写倒是没有错也可以过。
但是!这个题题面里说的是最多k个,所以其实根本不用考虑去掉非树边什么的,假如k>n-1的话只输出n-1条树边也是对的!这就省了好多代码了。其次,根本不用使用拓扑排序那样的处理过程(就是先去掉叶子这种),因为想一下dijkstra的过程就可以发现,每次从优先队列中取出来一个节点后,这个节点的前驱最短路其实已经确定了,只要在这时候把其前驱记录下来,根据dijkstra的每一步往外扩展一步的操作,按照这个顺序搞下去最后的记录表中的顺序其实就是拓扑序。。。。依次输出即可。
只能说自己对算法理解还是太浅吧,而且对题目也没有认真考虑,写了又臭又长的代码emmmm
自己的代码:
#include <iostream> #include <cstdio> #include <algorithm> #include <vector> #include <cstring> #include <set> #include <map> #include <string> #include<cmath> #include<queue> using namespace std; typedef long long LL; const int maxn = 6e5 + 5; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; LL dis[maxn]; struct Edge { int u,v,id;LL w; }edges[maxn*2]; struct node { int id;LL dis; node(int id,LL dis):id(id),dis(dis){} bool operator<(const struct node& rhs)const{ return dis>rhs.dis; } }; vector<int > G[maxn]; priority_queue<node> Q; int deg[maxn],pa[maxn],me,pe[maxn],fgs[maxn*2];//pe and fgs store id set<int> S; void addedge(int u,int v,int w,int id) { me++; edges[me].u=u,edges[me].v=v,edges[me].w=w,edges[me].id=id; G[u].push_back(me); me++; edges[me].u=v,edges[me].v=u,edges[me].w=w,edges[me].id=id; G[v].push_back(me); } void sssp(int s,int n,int k) { memset(dis,INF,sizeof(dis)); dis[s]=0; Q.push(node(s,0)); while(!Q.empty()) { node cn=Q.top(); Q.pop(); if(cn.dis!=dis[cn.id])continue; int cd=cn.dis,u=cn.id,len=G[cn.id].size(); for(int i=0;i<len;i++) { Edge & e=edges[G[u][i]]; if(dis[e.v]>dis[u]+e.w) { if(pa[e.v]) { deg[pa[e.v]]--; fgs[pe[e.v]]=0; } deg[u]++; pa[e.v]=u; pe[e.v]=e.id; if(e.id==0) while(1); fgs[e.id]=1; dis[e.v]=dis[u]+e.w; Q.push(node(e.v,dis[e.v])); } } } if(k>=n-1)//其实是不用考虑的 { for(int i=1;i<=n;i++) if(i!=s) { cout<<pe[i]<<" "; } k-=n-1; for(int i=1;(i<<1)<=me&&k>0;i++) { if(fgs[i]==0) { k--; cout<<i<<" "; } } return ; } for(int i=1;i<=n;i++) { if(deg[i]==0) { S.insert(i); } } int cc=n-1; while(!S.empty()&&k<cc) { cc--; int cur=(*S.begin()); int pre=pa[cur],pid=pe[cur]; fgs[pid]=0; deg[pre]--; S.erase(S.begin()); if(deg[pre]==0) { S.insert(pre); } } for(int i=1;(i<<1)<=me;i++) { if(fgs[i]!=0) cout<<i<<" "; } } int main() { ios::sync_with_stdio(0); cin.tie(0); int n,m,k,u,v,w; cin>>n>>m>>k; for(int i=1;i<=m;i++) { cin>>u>>v>>w; addedge(u,v,w,i); } cout<<k<<"\n";//其实没必要输出k个 sssp(1,n,k); return 0; }
官方代码:
#include <bits/stdc++.h> using namespace std; vector<pair<int, pair<int, int>>> g[300043]; int main() { int n, m, k; scanf("%d %d %d", &n, &m, &k); for (int i = 0; i < m; i++) { int x, y, w; scanf("%d %d %d", &x, &y, &w); --x; --y; g[x].push_back(make_pair(y, make_pair(w, i))); g[y].push_back(make_pair(x, make_pair(w, i))); } set<pair<long long, int>> q; vector<long long> d(n, (long long)(1e18)); d[0] = 0; q.insert(make_pair(0, 0)); vector<int> last(n, -1); int cnt = 0; vector<int> ans; while (!q.empty() && cnt < k) { auto z = *q.begin(); q.erase(q.begin()); int k = z.second; if (last[k] != -1) { cnt++; ans.push_back(last[k]); } for (auto y : g[k]) { int to = y.first; int w = y.second.first; int idx = y.second.second; if (d[to] > d[k] + w) { q.erase(make_pair(d[to], to)); d[to] = d[k] + w; last[to] = idx; q.insert(make_pair(d[to], to)); } } } printf("%d\n", ans.size()); for (auto x : ans) printf("%d ", x + 1); }