标签:ext 保留 除了 pre 并且 输出 ges shu algo
题目大意:
输入一张n个,点m条边的简单图,现需要保留最多k条边,问保留那些,可以使更多的点到1是之前图上的最短路。
思路:
可以用Dijkstra扩展k个节点,然而我最短路只会spfa,所以我用了类似其思想的一种贪心。
每条边除了记录基本信息,再记录一下能到达的下一个节点按这条路径到1的距离,每次选这个距离最小的边。
具体就是从1开始,先算出它连的边的那个距离,再往堆里加边,堆按那个距离排序,每次取一条那个距离最小的、并且所连点还没访问给的边,输出其序号。
1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 #include<cstring> 5 6 using namespace std; 7 8 const int Maxn=300005,Maxm=300005; 9 10 int head[Maxn],n,m,k,geshu=0,used[Maxn]={0}; 11 long long dis[Maxm]; 12 13 struct node 14 { 15 int zhong,next,qu,xuhao; 16 long long li; 17 node() 18 { 19 zhong=0; 20 next=0; 21 qu=0; 22 xuhao=0; 23 li=0; 24 } 25 bool operator < (const node &syy)const 26 { 27 return li>syy.li; 28 } 29 }bian[Maxm*3]; 30 31 priority_queue<node> dui; 32 33 void add(int qidian,int zhongdian,int quan,int xu) 34 { 35 geshu++; 36 bian[geshu].zhong=zhongdian; 37 bian[geshu].qu=quan; 38 bian[geshu].next=head[qidian]; 39 bian[geshu].xuhao=xu; 40 head[qidian]=geshu; 41 } 42 43 void getdata() 44 { 45 scanf("%d%d%d",&n,&m,&k); 46 for(int i=1;i<=m;i++) 47 { 48 int a,b,c; 49 scanf("%d%d%d",&a,&b,&c); 50 add(a,b,c,i); 51 add(b,a,c,i); 52 } 53 if(k>=n)k=n-1; 54 printf("%d\n",k); 55 } 56 57 int main() 58 { 59 getdata(); 60 int dang=head[1]; 61 used[1]=1; 62 dis[1]=0; 63 while(dang) 64 { 65 bian[dang].li=dis[1]+bian[dang].qu; 66 dui.push(bian[dang]); 67 dang=bian[dang].next; 68 } 69 for(int i=1;i<=k;i++) 70 { 71 node ans=dui.top(); 72 dui.pop(); 73 while(used[ans.zhong]&&!dui.empty()) 74 { 75 ans=dui.top(); 76 dui.pop(); 77 } 78 used[ans.zhong]=1; 79 dis[ans.zhong]=ans.li; 80 // printf("dian=%d;dis=%I64d\n",ans.zhong,dis[ans.zhong]); 81 printf("%d ",ans.xuhao); 82 int zh=ans.zhong; 83 dang=head[zh]; 84 while(dang) 85 { 86 bian[dang].li=bian[dang].qu+dis[zh]; 87 dui.push(bian[dang]); 88 dang=bian[dang].next; 89 } 90 } 91 printf("\n"); 92 return 0; 93 }
标签:ext 保留 除了 pre 并且 输出 ges shu algo
原文地址:https://www.cnblogs.com/LiqgNonqfu/p/9967034.html