HNU13247Connected Caves (拓扑)

Connected Caves
Time Limit: 2000ms, Special Time Limit:5000ms, Memory Limit:65536KB
Total submit users: 6, Accepted users: 5
Problem 13247 : Special judge
Problem description

You’re an intern at Greedy Cave Plundering Corporation. Your new job is to help with one of GCPC’s projects: extracting valuable gemstones from a network of connected caves. The history of the project so far:

• Tom, one of the project managers, has hired Jill, a gemstone expert. She has already surveyed these caves and determined the value of all gemstones in each cave.

• Ruby, another project manager (PM), has been busy “guesstimating” a time frame, the budget and possible profits for this project.

• Evelyn and Jerry (also PMs) have hired two cave diggers and instructed them to extract the gemstones.

• The cave diggers needed equipment to extract the gemstones and transport them to the surface. So Jimmy (another PM) ordered some machines. Sadly, he did not communicate well with the cave diggers - he bought machines that are way too big for the current passage ways between caves.

• To fix this, Jimmy was fired and James, his successor, has ordered a very big drilling machine, so the cave diggers can widen the passage ways. However, James was fearful of cutting into his salary bonus, so he bought the cheapest machine he could find. Soon, after widening the passage way from the surface into cave 1, the cave diggers found out that the new drilling machine is very heavy and not so powerful, so it can only be used to widen a passage way that goes downwards. Once it has reached a lower cave, it can not be carried back up because of its weight.

• This is when Alice, the project manager in charge of budget planning, announced she would ignore further requests for more equipment.

• In an eight hour meeting discussing the problems of the project, it was decided to limit the project expenses. So, if further drilling would hurt profits or if the drilling machine reaches a cave where it can not go on, it will just be abandoned. Using the other machines, the cave diggers will then be able to harvest at least some of the gemstones. Afterwards, the dig site will probably be sold to another company. Ruby is already thinking about hiring her brother as a sales expert...

This is where you come in. Tom has hired you to determine which passage ways should be widened and thereby which caves should be visited to maximize profits. Widening a passage way requires energy, materials and so on. You have to consider these costs. You will be given a map of all caves and passage ways. The map was created by the cave diggers, so it should be accurate. It contains only passage ways the drilling machine can handle, including the correct drilling direction. All caves in the map are reachable from cave one.


Input

The input starts with a line containing T, the number of test cases (1 ≤ T ≤ 10). Each test case starts with a line containing two integers: N, the number of caves, and E, the number of passage ways (1 ≤ N ≤ 2 · 10^4; 0 ≤ E ≤ 10^5). The second line contains N integers v1 v2... vN. videscribes the value of all gemstones in cave i (0 ≤ vi≤ 10^4). Each of the next E lines contains three integers: a e b e c e . Such a line represents one of the possible direct passage ways from cave a e to cave b e , widening this passage way will cost c e (1 ≤ a e ,b e ≤ N; 0 ≤ c e ≤ 10^4). It is guaranteed that the input contains only valid digging directions, i.e. cave b e will be strictly deeper than a e . You always start from cave number 1, because the digging machine is already there and there are no caves above.


Output

Output two lines for every test case. In the first line print two integers P and C, where P is the profit of the best possible route from top to bottom and C is the number of visited caves on that path. In the second line print the IDs of those caves, ordered from top to bottom. If there are multiple solutions with optimal profit, print any.


Sample Input
3
1 0
10
4 3
10 20 30 40
1 2 19
1 3 23
1 4 34
4 4
10 20 30 40
1 2 10
2 4 20
1 3 20
3 4 10
Sample Output
10 1
1
17 2
1 3
50 3
1 3 4
Problem Source
GCPC 2014


题意:给出n个点1~n,m条边,每个点有一个价值,给出的每条边是有向边a-->b 花费c,无环图,得到的总价值= 走过的点的价值和-走过边的花费。从点1开始走,问最大能得多少价值。有多少个点,都有哪些点组成。

解题:就用拓扑序列做。须自写scanf函数,否则超时。

#include<stdio.h>
#include<vector>
using namespace std;

#define LL int
const int N = 20005;
#define inf -600000000

struct TO
{
    int v;
    LL c;
};
LL node[N],valu[N];
int fath[N],n,in[N];
vector<TO>tmap[N];
void init()
{
    for(int i=1; i<=n;i++)
    {
        in[i]=0; node[i]=inf; tmap[i].clear();
    }
}
void topu()
{
    int k,to[N],id;
    LL sum;
    k=0;
    for(int i=2;i<=n;i++)
        if(!in[i])
            to[++k]=i;
    while(k)
    {
        int s=to[k]; k--;
        for(int i=0;i<tmap[s].size();i++)
        {
            int v=tmap[s][i].v;
            in[v]--;
            if(in[v]==0)
                to[++k]=v;
        }
    }
    to[++k]=1;
    node[1]=valu[1]; fath[1]=1;
    sum=node[1],id=1;
    while(k)
    {
        int s=to[k]; k--;
        for(int i=0;i<tmap[s].size();i++)
        {
            int v=tmap[s][i].v;
            in[v]--;
            if(in[v]==0)
                to[++k]=v;
            if(node[v]<node[s]+valu[v]-tmap[s][i].c)
                node[v]=node[s]+valu[v]-tmap[s][i].c,fath[v]=s;
            if(sum<node[v])
                sum=node[v],id=v;
        }
    }
    k=0;
    while(fath[id]!=id)
    {
        to[++k]=id; id=fath[id];
    }
    to[++k]=id;
    printf("%d %d\n%d",sum,k,to[k]);
    for(int i=k-1; i>0; i--)
        printf(" %d",to[i]);
    printf("\n");
}
inline void scanf(int &a)
{
    int flag=0;
    char ch;
    while(ch=getchar())
    {
        if(ch=='-')
        {
            flag=1; break;
        }
        if(ch>='0'&&ch<='9')
            break;
    }
    a=0;
    if(flag==0)
        a=ch-'0';
    while(ch=getchar())
    {
        if(ch<'0'||ch>'9')
            break;
        a=a*10+ch-'0';
    }
    if(flag)
        a=-a;
}
int main()
{
    int t,m,a,b,c;
    scanf(t);
    while(t--)
    {
        scanf(n);
        scanf(m);
        init();

        for(int i=1;i<=n;i++)
            scanf(valu[i]);
        TO ss;
        while(m--)
        {
            scanf(a); scanf(ss.v); scanf(ss.c);
            if(a==ss.v)
                continue;

            tmap[a].push_back(ss);
            in[ss.v]++;
        }
        topu();
    }
}


你可能感兴趣的:(拓扑排序)