Codeforces1076D. Edge Deletion(最短路树+bfs)

题目链接:http://codeforces.com/contest/1076/problem/D

题目大意:

一个图N个点M条双向边。设各点到点1的距离为di,保证满足条件删除M-K条边之后使得到点1的距离仍为di的点数量最多的情况下,输出剩余的K条边的编号(按输入顺序)。

   (2≤n≤3⋅105, 1≤m≤3⋅105, n−1≤m, 0≤k≤m)

解题思路:太菜了没写出来。。。

参考自博客:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9951711.html

用迪杰斯特拉在图中跑最短路,并且利用两个数组存被松弛节点的父节点和保存对应的边,然后用bfs贪心保留离源点近的边。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
int n,m,k;
struct qnode{
    int v;
    ll d;
    qnode(int a,ll b):v(a),d(b){}
    bool operator<(const qnode& x)const{
        return d>x.d;
    }
};
struct edge{
    int id,v;
    ll w;
    edge(int a,int b,ll c):id(a),v(b),w(c){}
};
vector<edge> mp[maxn];
void add(int id,int u,int v,ll w)
{
    mp[u].push_back(edge(id,v,w));
    mp[v].push_back(edge(id,u,w));
}
int vis[maxn],pree[maxn],pret[maxn];
ll dis[maxn];
priority_queue<qnode> pq;
void dij()
{
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f3f3f3f,sizeof(dis));
    dis[1]=0;
    pret[1]=1;
    pq.push(qnode(1,0));
    while(!pq.empty())
    {
        qnode q=pq.top();
        pq.pop();
        int u=q.v;
        if(vis[u]) continue;
        vis[u]=1;
        for(int i=0;i<mp[u].size();i++)
        {
            int id=mp[u][i].id;
            int v=mp[u][i].v;
            ll w=mp[u][i].w;
            if(!vis[v]&&dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                pret[v]=u;
                pree[v]=id;
                pq.push(qnode(v,dis[v]));
            }
        }
    }
}
vector<int> son[maxn];
queue<int> que;
vector<int> ans;
void bfs()
{
    que.push(1);
    while(!que.empty())
    {
        int u=que.front();
        que.pop();
        for(int i=0;i<son[u].size();i++)
        {
            int v=son[u][i];
            if(k>0)
            {
                ans.push_back(pree[v]);
                que.push(v);
                k--;
            }
            else break;
        }
    }
}


int main()
{
    ios_base::sync_with_stdio(false); cin.tie(0);
    cin>>n>>m>>k;
    for(int i=1;i<=m;i++)
    {
        int u,v;
        ll w;
        cin>>u>>v>>w;
        add(i,u,v,w);
    }
    dij();
    for(int i=2;i<=n;i++)
        son[pret[i]].push_back(i);
    bfs();
    cout<<ans.size()<<endl;
    if(ans.size()==0)
        return 0;
    cout<<ans[0];
    for(int i=1;i<ans.size();i++)
        cout<<" "<<ans[i];
    cout<<endl;
    return 0;
}

 

posted @ 2018-11-23 17:29  两点够吗  阅读(376)  评论(0编辑  收藏  举报