1. 程式人生 > >Educational Codeforces Round 54 (Rated for Div. 2) D. Edge Deletion

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

因為di定義為是圖上1到i點的最短路徑的長度,如果不限制邊數,那麼最少需要就是n - 1條邊,使得n個點用最短路徑邊連起來,迪傑斯特拉就是用已知最短路的點去更新其他點,那麼其他點的最短路一定會經過已知最短路的點,題中要求留k條邊good點最多,那肯定是最短路上的點,k是1,有兩個good點,k為2,有三個good點,。。。。類推下去,k >= n - 1,有n個good點,所以只要用迪傑斯特拉跑一遍最短路找到路徑上的邊即可,只需找到前k個(k < n - 1) 或n - 1個邊;

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int inf = 0x3f3f3f3f;
#define mp make_pair
#define pb push_back
#define fi first
#define se second
const int N = 3 * 1e5 + 5;

LL dis[N];
bool vis[N];
vector<pair<int,pair<int,int> > >ve[N];
typedef struct Node{
    LL w;
    int x,id;
    friend bool operator < (const Node &p,const Node &q)
    {
        return p.w > q.w;
    }
}Node;
priority_queue<Node>que;
vector<int>ans;

int main()
{
    int n,m,k;
    scanf("%d %d %d",&n,&m,&k);
    for(int i = 1;i <= m;++i){
        int u,v,w;
        scanf("%d %d %d",&u,&v,&w);
        ve[u].pb(mp(w,mp(v,i)));
        ve[v].pb(mp(w,mp(u,i)));
    }
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    dis[1] = 0;
    que.push((Node){0,1,0});
    while(!que.empty())
    {
        Node tmp = que.top();
        que.pop();
        if(vis[tmp.x]) continue;
        vis[tmp.x] = true;
        if(tmp.id) ans.pb(tmp.id);
        if(ans.size() == n - 1 || ans.size() == k) break;
        int len = ve[tmp.x].size();
        for(int i = 0;i < len;++i){
            int v = ve[tmp.x][i].se.fi;
            int id = ve[tmp.x][i].se.se;
            LL w = ve[tmp.x][i].fi;
            if(!vis[v] && dis[tmp.x] + w < dis[v]){
                dis[v] = dis[tmp.x] + w;
                que.push((Node){dis[v],v,id});
            }
        }
    }
    printf("%d\n",ans.size());
    for(int i = 0;i < ans.size();++i){
        printf("%d ",ans[i]);
    }
    printf("\n");
    return 0;
}