题目地址: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1677
首先要求最大生成树,来保证图的连通性(基于贪心的思想--尽量炸代价小的路,能炸得更多)
然后在资金足够的情况下,一一去炸代价小的路,直到钱不够当前最便宜的路了,break掉
代码:
#include<iostream> #include<vector> #include<algorithm> #include<cstdio> #include<cstring> using namespace std; int p[50005]; struct edge { int id; int x; int y; int w; }; edge e[100005]; bool ex[100005]; bool cmp(edge a,edge b) { return a.w>b.w; } bool vecmp(edge a,edge b) { return a.id<b.id; } int find(int x) { if(p[x]==x) return x; else return p[x]=find(p[x]); } int n,m; int cc; void kruskal() { for(int i=0;i<n;i++) p[i]=i; int cc=n; for(int i=0;i<m;i++) { int x=find(e[i].x); int y=find(e[i].y); if(x!=y) { ex[i]=1; p[x]=y; cc--; if(cc==1) break; } } } vector<edge> ve; int main() { int flag=0; long long s; int x,y,w; while( cin>>n>>m>>s) { memset(ex,0,sizeof(ex)); ve.clear(); if(flag==1) cout<<endl; if(flag==0) flag=1; for(int i=0;i<m;i++) { scanf("%d%d%d",&x,&y,&w); e[i].x=x-1; e[i].y=y-1; e[i].w=w; e[i].id=i; } sort(e,e+m,cmp); kruskal(); for(int i=m-1;i>=0;i--) { if(ex[i]==1) continue; if(s<e[i].w) break; ve.push_back(e[i]); s-=e[i].w; } cout<<ve.size()<<endl; if(ve.size()>0) { sort(ve.begin(),ve.end(),vecmp); for(int i=0;i<ve.size()-1;i++) cout<<ve[i].id+1<<" "; cout<<ve[ve.size()-1].id+1; cout<<endl; } } }