[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 }