Oil Deal(最大生成树)

ZOJ Problem Set - 2677
Oil Deal

Time Limit: 5 Seconds      Memory Limit: 32768 KB      Special Judge

Oil is a very important strategic resource. Recently United Statesof Antarctica invaded the rich in oil country of Qari, and now tryto keep the control of the oil transportation system. The systemconsists of pipelines that connect different nodes --- oil sources andmain country cities and ports. It is designed in such a way thatit is possible to transport oil from any node to any other one.

However the resisting native forces of Qari are not satisfied withthe situation. So they continuously perform terroracts, blowing up some oil pipelines. Recently terrorists havedecided to perform a series of explosions and want to hurtthe oil pipeline system as much as possible.

For each pipeline the terrorists know the cost of blowing it up.They have a fixed sum of money and want to explode as many pipesas possible for this sum. However, since they still needoil for themselves in different regions of the country, they wantthe system still be able to transport oil from any node to any otherone. Help them to find out which pipes to blow up.

Input

There are several test cases in the input. The first line of each case contains n --- the number of nodes,m --- the number of pipelines, and s --- the amount of moneyterrorists have (2 <= n <= 50,000 , 1 <= m <= 100,000 ,0 <= s <= 1018 ). The following m lines contain informationabout pipelines --- for each pipeline the nodes it connectsand the cost of blowing it up is specified (cost does not exceed 109 ).

Oil can be transported along each pipeline in both directions, each two nodes are connected by at most one pipeline.

There is an empty line between cases.

Output

On the first line of each case print the maximal numberof pipelines terrorists can blow up. On the second line printthe numbers of these pipelines (pipelines are numbered startingwith 1 as they are listed in the input file).There should be an empty line between cases.

Example

Input Output
6 7 10
1 2 3
1 3 3
2 3 3
3 4 1
4 5 5
5 6 4
4 6 5
2
1 5

Source: Andrew Stankevich's Contest #8
Submit    Status

先求原图的一棵最大生成树,树中的管道不能被破坏,对于不在树中的管道,在总耗费不超过S的前提下选择被破坏的管道。
这题本身不难,但是题意很模糊。有以下几点需要注意
1.s和破坏每个管道的cost都是整数,注意s需用64位;
2.可以被破坏的管道数量可以是0,在此情况下依然要输出一个空行。
3.对于一组输入数据,答案不唯一,输出其一即可。

AC Code:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LL long long
#define MAXI 2147483647
#define MAXL 9223372036854775807
#define eps (1e-8)
#define dg(i) cout << "*" << i << endl;

using namespace std;

struct Edge
{
    int id;
    int u, v;
    int cost;
    bool tag;  //tag == 1: to be exploded
}e[100005];
int set[50005];

int FindSet(int x)
{
    if(x != set[x]) return set[x] = FindSet(set[x]);
    return x;
}

bool operator < (const Edge& x, const Edge& y)
{
    return x.cost > y.cost;
}

int main()
{
    int n, m, cnt;
    long long s;
    vector ans;
    bool blank = 0;
    while(scanf("%d %d %lld", &n, &m, &s) != EOF)
    {
        if(blank) puts("");
        else blank = 1;
        while(!ans.empty()) ans.pop_back();
        for(int i = 1; i <= n; i++) set[i] = i;
        for(int i = 1; i <= m; i++)
        {
            scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].cost);
            e[i].id = i;
            e[i].tag = 1;
        }
        sort(e + 1, e + 1 + m);
        cnt = 0;  //记录最大生成树中已有的边数
        for(int i = 1; cnt != n - 1; ++i)
        {
            int Set_v = FindSet(e[i].v);
            int Set_u = FindSet(e[i].u);
            if(Set_u != Set_v)
            {
                if(Set_u > Set_v) set[Set_u] = Set_v;
                else set[Set_v] = Set_u;
                cnt++;
                e[i].tag = 0;  //更改标记
            }
        }
        for(int i = m; i > 0; i--)
        {
            if(e[i].tag)
            {
                if(s >= e[i].cost) s -= e[i].cost;
                else break;
                ans.push_back(e[i].id);
            }
        }
        printf("%d\n", ans.size());
        if(!ans.empty())  //注意必须在ans不为空的情况下执行,否则非法访问内存
        {
            vector::iterator it = ans.begin();
            printf("%d",*it);
            for(it++; it != ans.end(); it++)
                printf(" %d", *it);
        }
        printf("\n");  //就算ans为空也要输出一个空行
    }
    return 0;
}



你可能感兴趣的:(ACM题解)