poj1511 spfa 单向路

Invitation Cards

Time Limit: 8000MS   Memory Limit: 262144K
Total Submissions: 32390   Accepted: 10712

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

2
2 2
1 2 13
2 1 33
4 6
1 2 10
2 1 60
1 3 20
3 4 10
2 4 5
4 1 50

Sample Output

46
210

题意:你现在在一号车站,你有很多同伴,现在你们要出发去所有其余的车站,做完任务后返回,你们可以随意选择路线,不同的路线花费不同,要你求出最小的花费总和,一个车站去一个人,确保人足够,同时确保每个车站都是能到达的。

思路:最短路问题,spfa,emmmmmm,

我一开始的代码(ac):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<cstdlib>
#include<map>
#include<deque>
#include<queue>
#include<list>
const int inf=0x3f3f3f3f;
const int MOD=1e9+7;
#define LL long long
#define ME0(x) memset(x,0,sizeof(x))
#define MEF(x) memset(x,-1,sizeof(x))
#define MEI(x) memset(x,inf,sizeof(x))
using namespace std;
int t,n,m,s,e,d,cnt,firstg[1000005],firstr[1000005],disg[1000005],disr[1000005],flag[1000005];
queue<int> q;
struct LX
{
    int st,ed,di,nextg,nextr;
}lx[1000005];
void add(int x,int y,int z,int c)
{
    lx[c].st=x;
    lx[c].ed=y;
    lx[c].di=z;
    lx[c].nextg=firstg[x];
    firstg[x]=c;
    lx[c].nextr=firstr[y];
    firstr[y]=c;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        cnt=0;
        ME0(firstg);
        ME0(firstr);
        for(int m1=1;m1<=m;m1++)
        {
            scanf("%d%d%d",&s,&e,&d);
            add(s,e,d,++cnt);
        }
        MEI(disg);
        ME0(flag);
        disg[1]=0;
        q.push(1);
        flag[1]=1;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            flag[x]=0;
            for(int i=firstg[x];i!=0;i=lx[i].nextg)
            {
                int y=lx[i].ed;
                if(disg[y]>disg[x]+lx[i].di)
                {
                    disg[y]=disg[x]+lx[i].di;
                    if(!flag[y])
                    {
                        q.push(y);
                        flag[y]=1;
                    }
                }
            }
        }
        MEI(disr);
        ME0(flag);
        disr[1]=0;
        q.push(1);
        flag[1]=1;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            flag[x]=0;
            for(int i=firstr[x];i!=0;i=lx[i].nextr)
            {
                int y=lx[i].st;
                if(disr[y]>disr[x]+lx[i].di)
                {
                    disr[y]=disr[x]+lx[i].di;
                    if(!flag[y])
                    {
                        q.push(y);
                        flag[y]=1;
                    }
                }
            }
        }
        LL ans=0;
        for(int n1=1;n1<=n;n1++)
        {
            ans=ans+disr[n1]+disg[n1];
        }
        printf("%lld\n",ans);
    }
}

没什么特别的想法,就是普通的spfa,第一遍 lx[i].nextg 存的是起点相同的边的前一条边的编号,firstg[i]存的是以i开始的最后一条边,disg[i] 表示的是起点到 i 点的最小费用,第二遍 lx[i].nextr 存的是终点相同的边的前一条边的编号,firstr[i]存的是以 i 结尾的最后一条边,disr[i] 表示的是 i 到起点的最小费用,松弛操作都差不多。

emmmmm  感觉自己说出来都好拗口,然后看了别人的代码,感觉自己太弱了。。。。

存两个表,第一个表起点就是起点,终点就是终点,权值还是权值,next也还是next,第二个表把起点和终点换一下,其余的不变,这样的话,用第一个跑spfa得到的就是点 1 到其余点的最小费用,用第二个得到的还是点 1 到其余点的最小费用,但前面我们是把起点和终点换了一下的,所以得到的其实是其余点到点 1 的最小费用,最后只要把两遍spfa得到的dis数组全部加起来就是答案了

最后需要注意的就是scanf输入,用cin会超时,答案是 long long 类型,用int会爆掉然后会wa。。。。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<set>
#include<cstdlib>
#include<map>
#include<deque>
#include<queue>
#include<list>
const int inf=0x3f3f3f3f;
const int MOD=1e9+7;
#define LL long long
#define ME0(x) memset(x,0,sizeof(x))
#define MEF(x) memset(x,-1,sizeof(x))
#define MEI(x) memset(x,inf,sizeof(x))
using namespace std;
int t,n,m,e,s,d,cnt,firstr[1000005],firstg[1000005];
queue<int> q;
struct LX
{
    int st,ed,di,next;
}lxr[1000005],lxg[1000005];
void add(int x,int y,int z,int c,LX *l,int *first)
{
    l[c].st=x;
    l[c].ed=y;
    l[c].di=z;
    l[c].next=first[x];
    first[x]=c;
}
LL spfa(int s,LX *lx,int *first)
{
    int flag[1000005],dis[1000005];
    ME0(flag);
    MEI(dis);
    q.push(s);
    flag[s]=1;
    dis[s]=0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        flag[x]=0;
        for(int i=first[x];i!=0;i=lx[i].next)
        {
            int y=lx[i].ed;
            if(dis[y]>dis[x]+lx[i].di)
            {
                dis[y]=dis[x]+lx[i].di;
                if(!flag[y])
                {
                    q.push(y);
                    flag[y]=1;
                }
            }
        }
    }
    LL re=0;
    for(int n1=1;n1<=n;n1++)
    {
        re+=dis[n1];
    }
    return re;
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        cnt=0;
        ME0(firstg);
        ME0(firstr);
        for(int m1=1;m1<=m;m1++)
        {
            scanf("%d%d%d",&s,&e,&d);
            cnt++;
            add(s,e,d,cnt,lxr,firstr);
            add(e,s,d,cnt,lxg,firstg);
        }
        LL ans=0;
        ans+=spfa(1,lxr,firstr)+spfa(1,lxg,firstg);
        printf("%lld\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/ecjtu_17_TY/article/details/81503709