Educational Codeforces Round 54 (Rated for Div. 2) D Edge Deletion (最短路)

题意:给你一个无向图,之后又n个点m条边,现在让你将整个图删成只剩下k条边,并且保证删除后的边的最短路不变,现在问你剩下的边的编号是多少

思路:删除的边要保证最短路不变,那么就可以看出,松弛的边是一定不能删除的,因为删除他之后我们的最短路肯定会改变的,那么我们将松弛的边全部找出来,取完之后我们会发现每一个前驱只可能有一个后继,那么这其实就是一棵树了,之后我们从树的根节点里选出k个点就好了。

代码: 

#include <bits/stdc++.h>
using namespace std;
const long long INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 3e5+10;
vector<tuple<int,long long,int> >V[maxn];
vector<int>A;
long long dis[maxn] ;
int vis[maxn] , pre[maxn];
int n , m , k , u , v , w;
struct node
{
	int v;
	long long num;
	node (int a,long long b) :v(a),num(b){}
	bool operator < (const node b) const
	{
		return b.num < num;
	}
};
void dij(int s)
{
    priority_queue<node>Q;
	for(int i = 1 ; i <= n ; i ++) dis[i] = INF , vis[i] = 0,pre[i] = -1;
	dis[s] = 0;
	k++;
	Q.push(node(s,0));
	while(!Q.empty())
    {
        node p = Q.top(); Q.pop();
        int u = p.v;
        if(vis[u]) continue;
        vis[u] = 1;
        A.push_back(pre[u]);
        k--;
        if(k == 0) break;
        for(int i = 0 ; i < V[u].size() ; i ++)
        {
            int v,id;
            long long w;
            tie(v,w,id) = V[u][i];
            if(dis[v] > dis[u] + w)
            {
                dis[v] = dis[u] + w;
                pre[v] = id;
                Q.push(node(v,dis[v]));
            }
        }
    }
    cout<<A.size() - 1<<endl;
    for(int i = 1 ; i < A.size() ; i++)
    {
        cout<<A[i]<<" ";
    }
    puts("");
}
int main()
{

	scanf("%d%d%d",&n,&m,&k);
	for(int i = 0 ; i < m ; i ++)
	{
		scanf("%d%d%d",&u,&v,&w);
		V[u].emplace_back(v,w,i+1);
		V[v].emplace_back(u,w,i+1);
	}
	dij(1);
	return 0;
}

 

展开阅读全文

没有更多推荐了,返回首页