传送门:https://codeforces.com/contest/1076/problem/D
D. Edge Deletion
time limit per test 2.5 seconds
memory limit per test 256 megabytes
input standard input
output standard output
You are given an undirected connected weighted graph consisting of n vertices and m edges. Let's denote the length of the shortest path from vertex 1 to vertex i as di.
You have to erase some edges of the graph so that at most k edges remain. Let's call a vertex i good if there still exists a path from 1 to i with length didi after erasing the edges.
Your goal is to erase the edges in such a way that the number of good vertices is maximized.
Input
The first line contains three integers nn, mm and k (2≤n≤3⋅105, 1≤m≤3⋅105n−1≤m, 0≤k≤m) — the number of vertices and edges in the graph, and the maximum number of edges that can be retained in the graph, respectively.
Then mm lines follow, each containing three integers xx, yy, ww (1≤x,y≤n, x≠y, 1≤w≤109), denoting an edge connecting vertices x and y and having weight w.
The given graph is connected (any vertex can be reached from any other vertex) and simple (there are no self-loops, and for each unordered pair of vertices there exists at most one edge connecting these vertices).
Output
In the first line print e — the number of edges that should remain in the graph (0≤e≤k).
In the second line print ee distinct integers from 1 to m — the indices of edges that should remain in the graph. Edges are numbered in the same order they are given in the input. The number of good vertices should be as large as possible.
Examples
input
3 3 2
1 2 1
3 2 1
1 3 3
output
2
1 2
input
4 5 2
4 1 8
2 4 1
2 1 3
3 4 9
3 1 5
output
2
3 2
题意:给定一张图,n个节点,m条边,现要求保留其中的最多k条边,使得删边后的图中节点1到各点的最短路长度仍为删除前的最短路长度的节点数最多,求保留的边,2≤n≤300000, 1≤m≤300000, n−1≤m, 0≤k≤m;(可能描述不是很清楚,没看懂就看题目吧
解法:只需跑一遍dijkstra求一下节点1到各点的最短路,实际上边权为正的连通图生成的是一颗树,称之为最短路树(至于为啥是树:从dijkstra算法思想大概可以看出来吧)那么找出棵树后从根节点1跑dfs或者bfs就行了吧(:
附code:
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int, int>
#define mem(a,b) memset(a,b,sizeof(a))
#define per(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a,b) for(int i=a;i>=b;i--)
#define pi acos(-1.0)
#define inf 0x3f3f3f3f
typedef long long ll;
template <class T> inline void read(T &x) {
x = 0;int f = 1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
x=x*f;
}
template<typename E> E gcd(E a,E b){return b==0?a:gcd(b,a%b);}
template<typename E> E ex_gcd(E a,E b,E &x,E&y) {if(b==0){x=1;y=0;}else {ex_gcd(b,a%b,y,x);y-=(a/b)*x;}}
template<typename E> E quick_pow(E a,E b,E c){E ans=1;while(b){if(b&1) ans=ans*a%c;a=a*a%c;b>>=1;}return ans;}
template<typename E> E inv1(E a,E b){return quick_pow(a,b-2,b);}
template<typename E> E inv2(E a,E b){E x,y;ex_gcd(a,b,x,y);return (x%b+b)%b;}
/*================Header Template==============*/
const double eps=1.0e-5;
const int maxn=300000+10;
const ll mod=10007;
int n,m,k,from,to,total=0;ll co;
ll dis[maxn];
vector<pair<int,pair<ll,int> > > edge[maxn];
bool vis[maxn];
vector<pair<int,int> > vec[maxn],tree[maxn];
int ans[maxn];
void dijkstra(int s)
{
priority_queue<pair<ll,int>,vector<pair<ll,int> >,greater<pair<ll,int> > > que;
per(i,1,n) dis[i]=1e18;dis[1]=0;
que.push(make_pair(0,s));
while(!que.empty()){
pair<ll,int> fron=que.top();que.pop();
if(vis[fron.second]) continue;
vis[fron.second]=true;
for(int i=0;i<edge[fron.second].size();i++){
int to=edge[fron.second][i].first,w=edge[fron.second][i].second.first;
if(dis[to]>dis[fron.second]+w){
dis[to]=dis[fron.second]+w;
que.push(make_pair(dis[to],to));
vec[to].clear();
vec[to].push_back(make_pair(fron.second,edge[fron.second][i].second.second));
}
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);mem(vis,false);
per(i,1,m){
read(from);read(to);read(co);
edge[from].push_back(make_pair(to,make_pair(co,i)));
edge[to].push_back(make_pair(from,make_pair(co,i)));
}
dijkstra(1);mem(vis,0);
per(i,1,n){
for(int j=0;j<vec[i].size();j++){
tree[i].push_back(make_pair(vec[i][j].first,vec[i][j].second));
tree[vec[i][j].first].push_back(make_pair(i,vec[i][j].second));
}
}
queue<int> qu;
qu.push(1);int cnt=0;vis[1]=true;
while(!qu.empty()&&total<k&&total<n-1){
int cur=qu.front();qu.pop();
for(int i=0;i<tree[cur].size();i++){
if(!vis[tree[cur][i].first]){
ans[++total]=tree[cur][i].second;
qu.push(tree[cur][i].first);
if(total==k) break;
vis[tree[cur][i].first]=true;
}
}
}
printf("%d\n",total);
for(int i=1;i<=total;i++) printf("%d%c",ans[i],i==total?'\n':' ');
}