1. 程式人生 > >Educational Codeforces Round 54 D - Edge Deletion 圖+貪心+dijkstra

Educational Codeforces Round 54 D - Edge Deletion 圖+貪心+dijkstra

題意:

給定n個點,m條邊的無向連通圖,定義d[j]為1號結點到j結點的最短距離

讓你刪去一些邊,讓邊數剩餘最多為k條,如果刪邊前後的兩個圖中d[j]相同的話,那j結點就是good點,

給定的邊編號1~m,現在讓你給出一種刪邊方案,是的good點儘量多;

思路:

單原點最短路,我們知道剩下的邊數e,最大是min(n-1, k); 

其實不用管剩餘多少條邊,按照dijkstra求最短路的過程,把前面訪問到的e條邊放進答案裡就是了;因為這樣訪問到的邊連線的點就是原圖中的最短路,現在選出來也是最短路;

 

#include<bits/stdc++.h>
using namespace std;
#define out fflush(stdout);
#define fast ios::sync_with_stdio(0),cin.tie(0);
#define FI first
#define SE second
typedef long long ll;
typedef pair<ll,ll> P;

const int maxn = 3e5 + 7;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const ll mod = 998244353;

ll n, m, k;
ll u, v, c;

struct no {
    ll u, c, id;
};
vector<no> vec[maxn];

struct node {
    ll d, v, id;
    bool operator< (const node &a) const {
        return (d > a.d);
    }
};
priority_queue<node> qu;

bool vis[maxn];
set<ll> ans;

int main() {
    scanf("%lld%lld%lld", &n, &m, &k);
    for(int i = 1; i <= m; ++i) {
        scanf("%lld%lld%lld", &u, &v, &c);
        vec[u].push_back(no{v, c, i});
        vec[v].push_back(no{u, c, i});
    }
    for(auto i : vec[1]) {
        qu.push(node{i.c, i.u, i.id});
    }
    vis[1] = 1;
    int anss = k;
    while(1) {
        if(qu.empty()) break;
        node t = qu.top(); qu.pop();
        ll u = t.v, d = t.d, id = t.id;
        if(vis[u]) continue;
        vis[u] = 1;
        if(k) {
            k--;
            ans.insert(id);
        }
        for(auto i : vec[u]) {
            if(vis[i.u]) continue;
            qu.push(node{d+i.c, i.u, i.id});
        }
    }
    cout << ans.size() << endl;
    int t = 0;
    for(auto i : ans) {
        t++;
        printf("%lld", i);
        if(t == ans.size()) break;
        printf(" ");
    }
    return 0;
}