[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); } }