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

http://codeforces.com/contest/1076/problem/D
题目大意:给出一个无向图,要求只保留K条边,并且使尽可能多的点保持原来到点1的最短距离.

题解:先用堆优化的DIJ跑出最短路径树,然后利用bfs,从叶子处开始减边(因为减叶子的边只会影响一个点的最短路径,而从非叶子减边会影响多个点的最短路径)

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 using namespace std;
  6 typedef long long ll;
  7 struct edge{
  8     int v;
  9     int id;
 10     ll val;
 11     int nex;
 12 }e[600005];
 13 struct pot{
 14     int v;
 15     ll dist;
 16     bool operator<(const struct pot & xx)const {
 17         return dist>xx.dist;
 18     }
 19 };
 20 int head[300004];
 21 ll dis[300004];
 22 bool ok[300005];
 23 int pre_e[300004],pre_v[300004];
 24 int n,m,k,cnt;
 25 int dev[300004];
 26 void dij(){
 27     priority_queue<struct pot>pq;
 28     struct pot aa;
 29     memset(dis,0x7f7f7f7f,sizeof(dis));
 30     dis[1]=0;
 31     aa.v=1;
 32     aa.dist=0;
 33     pq.push(aa);
 34     while(!pq.empty()){
 35         struct pot bb=pq.top();pq.pop();
 36         if(dis[bb.v]<bb.dist)continue; 
 37         for(int i=head[bb.v];i!=-1;i=e[i].nex){
 38             if(dis[e[i].v]>dis[bb.v]+e[i].val){
 39                 dis[e[i].v]=dis[bb.v]+e[i].val;
 40                 struct pot cc;
 41                 cc.v=e[i].v;
 42                 cc.dist=dis[e[i].v];
 43                 pre_v[e[i].v]=bb.v;
 44                 pre_e[e[i].v]=e[i].id;
 45                 pq.push(cc);
 46             }
 47         }
 48     }
 49 }
 50 void build() {
 51     for (int i = 2; i <= n; ++i) {
 52         int v = pre_v[i];
 53         int id = pre_e[i];
 54         ok[id] = 1;
 55         ++dev[v];
 56     }
 57 }
 58 void bfs(){
 59     if(k>=n-1){
 60         k=n-1;
 61         return ;
 62     }
 63     queue<int>pp;
 64     //k=n-1;
 65     int sk=n-1;
 66         for(int i=1;i<=n&&sk>k;i++){
 67             if(!dev[i]){
 68                 pp.push(i);
 69             }
 70         }
 71     while(sk>k){
 72         int i=pp.front();pp.pop();
 73                 dev[pre_v[i]]--;
 74                 ok[pre_e[i]]=0;
 75                 sk--;
 76                 if(dev[pre_v[i]]==0)pp.push(pre_v[i]);
 77     }
 78 }
 79 void adde(int x,int y,ll z,int s){
 80     e[cnt].v=y;
 81     e[cnt].val=z;
 82     e[cnt].nex=head[x];
 83     e[cnt].id=s;
 84     head[x]=cnt++;
 85     e[cnt].v=x;
 86     e[cnt].val=z;
 87     e[cnt].nex=head[y];
 88     e[cnt].id=s;
 89     head[y]=cnt++;
 90 }
 91 int main(){
 92     //freopen("in.txt","r",stdin);
 93     scanf("%d%d%d",&n,&m,&k);
 94     memset(head,-1,sizeof(head));
 95     for(int i=0;i<m;i++){
 96         int a,b;
 97         ll c;
 98         scanf("%d%d%lld",&a,&b,&c);
 99         adde(a,b,c,i);
100     }
101     dij();
102     build();
103     bfs();
104     cout << k << endl;
105     for(int i=0;i<m;i++){
106         if(ok[i])printf("%d ",i+1);
107     }
108     return 0;
109 }
View Code

猜你喜欢

转载自www.cnblogs.com/MekakuCityActor/p/9954232.html