刚开始想复杂了,一直做不出来,,,其实就是两遍dijkstra+优先队列(其实就是板子题,只要能有个好的板子,剩下的都不是事),做出来感觉好简单......
题意:有n个车站和n个志愿者,早上每个志愿者去一个站点,晚上回去,问最少的开销是多少。是一个有向图
先一遍dijkstra求出早上的开销,在把车站倒过来及1到4变成4到1,然后再一遍dijkstra求出晚上的开销。
不要用memset去初始化为INF, 本题如果用memset会wa,记得开long long;
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 6 const int INF = 1e9+10; 7 const int N = 1000010; 8 const int M = 1000010; 9 int tot; 10 11 struct Edge //dijkstra+优先队列板子 12 { 13 int v, cost, next; 14 }edge[M]; 15 16 struct qnode 17 { 18 int v,c; 19 bool operator < (const qnode &x) const { 20 return c > x. c; 21 } 22 }; 23 24 int head[M]; 25 bool vis[N]; 26 int dis[N]; 27 28 void addedge(int u, int v, int w) 29 { 30 edge[tot]. v = v; 31 edge[tot]. cost = w; 32 edge[tot]. next = head[u]; 33 head[u] = tot ++; 34 } 35 36 void dijkstra(int st) 37 { 38 memset(vis, 0, sizeof(vis)); 39 for(int i=0;i<N;i++) 40 dis[i]=INF; //最好不要用memset去初始化为INF, 很容易wa 41 dis[st] = 0; 42 priority_queue <qnode> q; 43 q. push({st, 0}); 44 while(! q. empty()){ 45 qnode t = q. top(); 46 q. pop(); 47 if(vis[t. v]) 48 continue; 49 vis[t. v] = true; 50 for(int i = head[t. v]; i != -1; i = edge[i]. next){ 51 int v = edge[i]. v; 52 int cost = edge[i]. cost; 53 if(! vis[v] && dis[v] > dis[t. v] + cost){ 54 dis[v] = dis[t. v] + cost; 55 q. push({v, dis[v]}); 56 57 } 58 } 59 } 60 } 61 62 int a[N], b[N], c[N]; 63 64 int main(){ 65 int n, m,t; 66 scanf("%d",&t); 67 while(t--){ 68 scanf("%d%d", &n, &m); 69 tot = 1; 70 memset(edge,0,sizeof edge); 71 memset(head, -1, sizeof(head)); 72 for(int i=0;i<m;i++){ 73 scanf("%d%d%d", &a[i], &b[i], &c[i]); 74 addedge(a[i], b[i], c[i]); 75 } 76 dijkstra(1); //早上的 77 int sum=0; 78 for(int i=2;i<=n;i++){ 79 sum+=dis[i]; //把1到每个站的最小开销加起来 80 } 81 tot=1; 82 memset(edge,0,sizeof edge); 83 memset(head, -1, sizeof(head)); 84 for(int i=0;i<m;i++){ 85 addedge(b[i], a[i], c[i]); //正着是1到每个站,反过来就是每个站到1 86 } 87 dijkstra(1); //晚上的 88 for(int i=2;i<=n;i++){ 89 sum+=dis[i]; //把每个站到1的最小开销加起来 90 } 91 printf("%d\n",sum); 92 } 93 return 0; 94 }