题目地址: 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;
}
}
}