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

[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