POJ 1511:Invitation Cards

来源:互联网 发布:友声tm x数据管理软件 编辑:程序博客网 时间:2024/05/21 09:41
Invitation Cards
Time Limit: 8000MS Memory Limit: 262144KTotal Submissions: 26994 Accepted: 8952题目链接

Description

In the age of television, not many people attend theater performances. Antique Comedians of Malidinesia are aware of this fact. They want to propagate theater and, most of all, Antique Comedies. They have printed invitation cards with all the necessary information and with the programme. A lot of students were hired to distribute these invitations among the people. Each student volunteer has assigned exactly one bus stop and he or she stays there the whole day and gives invitation to people travelling by bus. A special course was taken where students learned how to influence people and what is the difference between influencing and robbery. 

The transport system is very special: all lines are unidirectional and connect exactly two stops. Buses leave the originating stop with passangers each half an hour. After reaching the destination stop they return empty to the originating stop, where they wait until the next full half an hour, e.g. X:00 or X:30, where 'X' denotes the hour. The fee for transport between two stops is given by special tables and is payable on the spot. The lines are planned in such a way, that each round trip (i.e. a journey starting and finishing at the same stop) passes through a Central Checkpoint Stop (CCS) where each passenger has to pass a thorough check including body scan. 

All the ACM student members leave the CCS each morning. Each volunteer is to move to one predetermined stop to invite passengers. There are as many volunteers as stops. At the end of the day, all students travel back to CCS. You are to write a computer program that helps ACM to minimize the amount of money to pay every day for the transport of their employees. 

Input

The input consists of N cases. The first line of the input contains only positive integer N. Then follow the cases. Each case begins with a line containing exactly two integers P and Q, 1 <= P,Q <= 1000000. P is the number of stops including CCS and Q the number of bus lines. Then there are Q lines, each describing one bus line. Each of the lines contains exactly three numbers - the originating stop, the destination stop and the price. The CCS is designated by number 1. Prices are positive integers the sum of which is smaller than 1000000000. You can also assume it is always possible to get from any stop to any other stop.

Output

For each case, print one line containing the minimum amount of money to be paid each day by ACM for the travel costs of its volunteers.

Sample Input

22 21 2 132 1 334 61 2 102 1 601 3 203 4 102 4 54 1 50

Sample Output

46210

Source

Central Europe 1998

题目意思:
第一行输入一个数代表有这么多组测试数据,然后输入两个数,第一个是公交站点的个数,第二个是公交线路的条数,
接下来是线路。总部在顶点1,要向每个顶点派一个人,然后并让他们各自从当前顶点在回到1,求所有人所花的最少
路费的值。
因为做这个题目,新接触了一个求最短路的算法:Spfa。
费用总和 = 1到所有点的最短路和 + 所有点到1的最短路和。
Spfa算法讲解链接
这个链接讲得挺详细的。感觉Spfa挺节省空间。
上面看的时候最短理解的是他的st数组,最后终于搞明白。st[u]数组代表以边u为顶点的边(相当于链表)的头。通过头找到那些
能从u到v的点。看了好久才明白。
看他人的思路都是先按原图求1到所有点的最短路,然后向所有路径反过来,再求1到所有点的最短路相当于从各个点回到了顶点1.
按照这个思路,感觉Dijstra也可以,但是普通的Dijstra都是用二维矩阵存图,这个题目顶点最多一百万个,二维矩阵太大了。然后
就是时间复杂度的问题,时间复杂度n^2,n大了后真的挺大。所以他们都说用Dijstra+heap,看了之后,又看了Spfa,感觉没有差别这两个算法。想法都是一样的。用Spfa只用存边的关系就行了,的确在顶点多的时候,节省好多空间。在加上定义的相当于指针的数组,不用像普通Dijstra那样,要将所有点过一遍,for循环要是1~n,只用过和当前点有关系的就行了。这样时间复杂度也降低了很多。

#include<iostream>#include<cstdio>#include<queue>#define INF 0x3f3f3f3f#define MAXN 1000010using namespace std;struct node             ///节点类型{    int v;              ///起点为u终点为v    int w;              ///u到v的权值    int next;           ///next指向下一条以u为顶点的边};struct node edge[2][MAXN];/**edge[0][MAXN]用来存放原来的路,edge[1][MAXN]用来存放将所有路反过来的情况。**/long long dis[MAXN];    ///用来存放最短路径int sub[2][MAXN];       ///用来存放下一个所要获取的位置的数组int vis[MAXN];          ///用于标记的数组long long ans;          ///用来存放答案,根据题中输入,答案可能很大,定义为long longint N,M;                ///N个公交站点,M条公交线路void GetEdge()          ///获取边信息{    int s,d,cost;       ///s起始站点,d终止站点,cost为s到d的花费    for(int i = 0; i <= M; i++) ///初始化为-1,代表指针是空的    {        sub[0][i] = -1;        sub[1][i] = -1;    }    for(int i = 0; i < M; i++)    {        scanf("%d%d%d",&s,&d,&cost);        edge[0][i].v = d;        edge[0][i].w = cost;        edge[0][i].next = sub[0][s];        sub[0][s] = i;        ///将图反过来,从d到s        edge[1][i].v = s;        edge[1][i].w = cost;        edge[1][i].next = sub[1][d];        sub[1][d] = i;    }}///参数k用来指示,当前Spfa算法所处理的图示原图(k = 0)还是与原图相反的图(k = 1)。void Spfa(int k){    int cur;    for(int i = 1; i <= N; i++)     ///进行初始化工作    {        vis[i] = 0;        dis[i] = INF;    }    vis[1] = 1;                     ///处理源点1    dis[1] = 0;    queue<int>qu;    qu.push(1);    while(!qu.empty())              ///队列不空    {        cur = qu.front();        qu.pop();        vis[cur] = 0;        int point = sub[k][cur];        while(point != -1)          ///以cur为起点进行松弛操作。        {            if(dis[cur] + edge[k][point].w < dis[edge[k][point].v])            {                dis[edge[k][point].v] = dis[cur] + edge[k][point].w;                if(vis[edge[k][point].v] == 0)                {                    vis[edge[k][point].v] = 1;                    qu.push(edge[k][point].v);                }            }            point = edge[k][point].next;        }    }}void CalAnswer() ///计算答案的函数{    for(int i = 1; i <= N; i++)        ans += dis[i];}int main(){    int T;    scanf("%d",&T);  ///T组测试数据    while(T--)    {        scanf("%d%d",&N,&M);  ///输入N条边,M条线路信息        ans = 0;              ///ans初始化为0        GetEdge();            ///调用函数输入边        Spfa(0);              ///用原图求1到其他顶点的最短路        CalAnswer();          ///计算答案        Spfa(1);              ///用于原图相反的图在求1到其他顶点的最短路        CalAnswer();           ///计算答案        printf("%lld\n",ans);    }}


0 0
原创粉丝点击