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
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 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 vec[maxn];

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

bool vis[maxn];
set 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;
}

 

你可能感兴趣的:(贪心,最短路,codefoces)