Educational Codeforces Round 54 D. Edge Deletion
题意:
n个点,m条边,删除一些边,剩下k条边,使得到节点1最短路径长度不变的节点数最多.
分析:
最短路原理题,我们考虑用dij求最短路的过程中,每加入一个新的点,都要引入一个新的边,如果k >= n,把n条关键边输出,如果k < n,在dij的过程中,直接找到k个点最短路就跳出,记录一下边的编号
参考代码
//
#include <bits/stdc++.h>
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define Pb push_back
#define FI first
#define SE second
#define For(i,a,b) for(LL i = a; i < b; ++i)
#define IOS ios::sync_with_stdio(false)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
LL dr[2][4] = {1,-1,0,0,0,0,-1,1};
typedef pair<LL,LL> P;
#define endl "\n"
struct Edge{
LL u,v,d;
LL id;
Edge(LL uu,LL vv,LL dd,LL idd):u(uu),v(vv),d(dd),id(idd){
}
};
const LL maxn = 3e5+10;
struct Dijstra{
#define INF 1e16
LL N,M,S,T;
LL K;
typedef pair<LL,LL> P;
vector<Edge> edges;
vector<LL> G[maxn];
bool done[maxn];
LL d[maxn];
LL p[maxn];
void init(){
cin>>N>>M>>K;
// for(LL i = 1;i <= N; ++i) G[i].clear();
// edges.clear();
// // scanf("%d %d %d %d",&N,&M,&S,&T);
// // cout<<N<<M<<S<<T<<endl;
S = 1;
LL u,v,w;
for(LL i = 1;i <= M; ++i){
scanf("%lld %lld %lld",&u,&v,&w);
AddEdge(u,v,w,i);
AddEdge(v,u,w,i);
}
}
void AddEdge(LL u,LL v,LL d,LL id){
edges.push_back(Edge(u,v,d,id));
LL m = edges.size();
G[u].push_back(m-1);
}
void solve(){
priority_queue<P,vector<P>,greater<P>> Q;
for(LL i = 1;i <= N; ++i) d[i] = INF;
d[S] = 0;
memset(done,0,sizeof(done));
Q.push(P(0,S));
LL cnt = 0;
std::vector<LL> v;
while(!Q.empty()){
P x = Q.top(); Q.pop();
LL u = x.second;
if(done[u]) continue;
if(p[u] != 0)
v.push_back(p[u]);
cnt++;
if(cnt == K+1)
break;
done[u] = true;
for(LL i = 0;i <(LL)G[u].size(); ++i){
Edge &e = edges[G[u][i]];
if(!done[e.v]&&d[e.v] > d[u]+e.d){
d[e.v] = d[u]+e.d;
p[e.v] = edges[G[u][i]].id;
Q.push(P(d[e.v],e.v));
}
}
}
cout<<v.size()<<"\n";
for(LL i = 0;i < (LL)v.size();++i)
printf("%lld%c", v[i]," \n"[i==(int) v.size()-1]);
}
};
Dijstra Dij;
int main(void)
{
Dij.init();
Dij.solve();
return 0;
}