链接:https://codeforces.com/problemset/problem/1076/D

题意:给你一个有n个顶点、m条边的无向带权图。需要删除一些边使得剩余的边数不超过k,如果一个点在原始图到顶点1的最短距离为d,在删边后的图中到顶点的最短距离仍是d,则称这种点是 good。问如何删边,使得 good点最多。

题解:dijkstra记录最短路径,在bfs在最短路径树上搜索一个大小为k的连通块即可。

#include <bits/stdc++.h>
#define IO_read ios::sync_with_stdio(false);cin.tie(0)
#define fre freopen("in.txt", "r", stdin)
#define _for(i,a,b) for(int i=a; i< b; i++)
#define _rep(i,a,b) for(int i=a; i<=b; i++)
using namespace std;
typedef long long ll;

const int maxn=3e5+5;
const long long inf_ll= (ll)1<<61;
struct qnode{
    int v;
    ll c;
    qnode(int _v=0, ll _c=0):v(_v), c(_c) {}
    bool operator <(const qnode &r) const{
        return c>r.c;
    }
};

struct Edge{
    int v;
    ll cost;
    int id;
    Edge(int _v=0, ll _cost=0, int _id=0): v(_v), cost(_cost), id(_id) {}
};

vector<Edge> E[maxn*2];
bool vis[maxn];
ll dis[maxn];
int pre[maxn];

void dijkstra(int n, int start)
{
    memset(vis, 0, sizeof(vis));
    for(int i=1; i<=n; i++) dis[i]=inf_ll;
    priority_queue<qnode> que;
    que.push(qnode(start, 0));
    dis[start]=0;
    while(!que.empty())
    {
        qnode tmp=que.top(); que.pop();
        int u=tmp.v;
        if(vis[u]) continue;
        vis[u]=true;
        for(int i=0; i<E[u].size(); i++)
        {
            int v=E[u][i].v;
            ll cost=E[u][i].cost;
            if(!vis[v] && dis[v]>dis[u]+cost)
            {
                dis[v]=dis[u]+cost;
                pre[v]=u;
                que.push(qnode(v, dis[v]));
            }
        }
    }
}

vector<int> ans;

void bfs(int k, int start)
{
    if(k==0) return;
    queue<int> que;
    que.push(start);
    while(!que.empty())
    {
        int u=que.front(); que.pop();
        for(int i=0; i<E[u].size(); i++)
        {
            int v=E[u][i].v;
            if(pre[v]==u){
                que.push(v);
                ans.push_back(E[u][i].id/2);
                if(ans.size()==k) return;
            }
        }
    }
}

int main()
{
    IO_read;
    //fre;
    int n, m, k;
    cin>>n>>m>>k;
    _rep(i, 1, m)
    {
        int u, v;
        long long w;
        cin>>u>>v>>w;
        E[u].push_back(Edge(v, w, i*2));
        E[v].push_back(Edge(u, w, i*2+1));
    }
    dijkstra(n, 1);
    bfs(k, 1);
    cout<<ans.size()<<"\n";
    _for(i, 0, ans.size())
        cout<<ans[i]<<" ";
    return 0;
}
12-29 14:50