ZOJ 2677 Oil Deal(最大生成树)

题意:破坏石油管道,现一直破坏各个管道所要付出的代价,问在有一定money并且要保证剩余的管道为生成树的情况下, 最多能破坏多少个管道,并将他们的编号从小到大输出来

思路:将边从大到小排序,构造生成树。 接下来最后剩余的不在最大生成树的边,从最小开始在满足条件下依次取即可。

这里注意: 答案不唯一,输出其中之一即可。

 

#include <iostream>
#include <algorithm>
#include <string.h>
#include <stdio.h>
#include <string>
#include <queue>
using namespace std;

int n,m;
int blank=0;
long long s;
int a,b,cost;
int ans[105000];

//若flag为true,则表明该边在生成树里。
//no表示该边的序号
struct Edge{
    int u,v;
    int cost;
    bool flag;
    int no;
    bool operator <(const Edge& temp) const
    {
        return temp.cost<cost;
    }
}edge[105000];

struct UF{
    int father[55000];

    void init(){
        for(int i=1;i<=n;i++){
            father[i]=i;
        }
    }

    int find_root(int x){
       if(father[x]!=x)
           father[x]=find_root(father[x]);
       return father[x];
    }

    void Union(int fa,int fb){
        father[fb]=fa;
    }
}uf;

int main()
{
    while(scanf("%d%d%lld",&n,&m,&s)!=EOF){
          if(blank)
            puts("");
          else
            blank=1;
          for(int i=0;i<m;i++){
            scanf("%d%d%d",&a,&b,&cost);
            edge[i].u=a;
            edge[i].v=b;
            edge[i].cost=cost;
            edge[i].no=i+1;
            edge[i].flag=false;
          }

          sort(edge,edge+m);

          int counts=0;
          uf.init();
          for(int i=0;i<m;i++){
            int u=edge[i].u;
            int v=edge[i].v;
            int fu=uf.find_root(u);
            int fv=uf.find_root(v);
            if(counts>=n-1)
                break;
            if(fu!=fv){
                edge[i].flag=true;
                uf.Union(fu,fv);
                counts++;
            }
          }
          int num=0;
          //从最小边权开始
          for(int i=m-1;i>=0;i--){
            if(!edge[i].flag){
                if(s>=edge[i].cost){
                    s-=edge[i].cost;
                    ans[num]=edge[i].no;
                    num++;
                }
                else{
                    break;
                }
            }
          }

          printf("%d\n",num);
          for(int p=0;p<num;p++){
                //如果直接按照"%d "格式输出,也会AC
                if(p==0)
                    printf("%d",ans[p]);
                else
                    printf(" %d",ans[p]);
          }
          printf("\n");
        }
    return 0;
}

 

posted @ 2013-08-24 19:55  辰曦~文若  阅读(402)  评论(2编辑  收藏  举报