[HDU 1535]Invitation Cards[SPFA反向思维]

题意: (欧洲人自己写的题面就是不一样啊...各种吐槽...果断还是看晕了)

有向图, 有个源叫CCS, 求从CCS到其他所有点的最短路之和, 以及从其他所有点到CCS的最短路之和.

思路:

返回的时候是多个源,但是因为终点只有一个,所以把所有边反向之后, 再SPFA一次源即可.

#include<cstdio>
#include<vector>
#include<queue>
const int MAXN=1000000+10;
typedef long long ll;
const ll inf=1e60;
using namespace std;
struct Node{
    int v,w;
};
vector<Node>mp1[MAXN];//正向建图
vector<Node>mp2[MAXN];//反向建图
int n,m;
ll cost[MAXN];

void SPFA(int u,vector<Node>mp[]){
    for(int i=2;i<=n;i++)cost[i]=inf;
    cost[1]=0;
    queue<int>Q;
    Q.push(u);
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        for(int i=0;i<mp[u].size();i++){
            int v=mp[u][i].v;
            int w=mp[u][i].w;
            if(cost[v]>cost[u]+w){
                cost[v]=cost[u]+w;
                Q.push(v);
            }
        }
    }
}


int main(){
    int _case;
    scanf("%d",&_case);
    while(_case--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            mp1[i].clear();
            mp2[i].clear();
        }
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            Node p1,p2;
            p1.v=u,p2.v=v,p1.w=p2.w=w;
            mp1[u].push_back(p2);
            mp2[v].push_back(p1);
        }
        SPFA(1,mp1);//正向求一次
        ll ans=0;
        for(int i=2;i<=n;i++){
            ans+=cost[i];
        }
        SPFA(1,mp2);//反向求一次
        for(int i=2;i<=n;i++){
            ans+=cost[i];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

自己敲一遍:

#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
const int MAXN = 1e6+5;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
typedef struct node
{
    int v,w;
    node(){}
    node(int _v, int _w):v(_v),w(_w){}
}node;

int n,m;
bool inq[MAXN];
ll cost[MAXN];
vector<node> g1[MAXN],g2[MAXN];

ll SPFA(int op)
{
    memset(cost,0x3f,sizeof(cost));
    memset(inq,false,sizeof(inq));
    cost[1] = 0;
    queue<int> q;
    q.push(1);
    inq[1] = true;
    while(!q.empty())
    {
        int now = q.front();q.pop();
        inq[now] = false;
        for(int i=0,v,w;i<((op==1)?g1[now].size():g2[now].size());i++)
        {
            if(op==1)
            {
                v = g1[now][i].v, w = g1[now][i].w;
            }
            else
            {
                v = g2[now][i].v, w = g2[now][i].w;
            }
            if(cost[v] > cost[now] + w)
            {
                cost[v] = cost[now] + w;
                if(!inq[v])
                {
                    q.push(v);
                    inq[v] = true;
                }
            }
        }
    }
    ll ret = 0;
    for(int i=2;i<=n;i++)
        ret += cost[i];
    return ret;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            g1[i].clear();
            g2[i].clear();
        }
        for(int i=0,u,v,w;i<m;i++)
        {
            scanf("%d %d %d",&u,&v,&w);
            g1[u].push_back(node(v,w));
            g2[v].push_back(node(u,w));
        }
        ll ans = 0;
        ans += SPFA(1);
        ans += SPFA(2);
        printf("%d\n",(int)ans);
    }
}



你可能感兴趣的:([HDU 1535]Invitation Cards[SPFA反向思维])