题目链接:
题目大意:
飞天鼠是班长,一天班主任买了一大包糖果,要飞天鼠分发给大家,班里面有n个人,但是学生A认为学生B比自己多的糖果数目不应该大于c,如果不满足自己的条件,学生A就会向老师告状,在这个班级里面泰迪熊的编号是1,班长的编号是n,班长想和泰迪熊的糖果相差最大,问:在满足m个学生的要求后,班长与泰迪熊的糖果相差最大是多少?
解题思路:
差分约束系统,|Xa-Xb| <= c,我们假设Xa小于Xb,把糖果的最大差当成边权,因为要满足全部人的要求,也就是要求所建图的最短路,用spfa+queue优化tle了,然后我就用了dijkstra+优先队列。感觉用邻接表+优先队列对dijkstra优化真是太美妙了,省去了很多的无用枚举,但是dijkstra的先天不足还是没有办法挽救~~~~
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <queue> 5 #include <vector> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 #define maxn 30010 10 11 struct Edge 12 { 13 int e, w; 14 Edge(int e=0, int w=0) : e(e),w(w) {} 15 }; 16 17 bool operator < (const Edge &a, const Edge &b) 18 { 19 return a.w > b.w;//dist小的优先级高 20 } 21 22 vector< vector<Edge> > G;//二维vector 23 //vector<Edge>G[maxn]要比前者慢,估计申请空间需要的时间也比较可观 24 bool vis[maxn]; 25 int n; 26 27 void dijkstra(); 28 29 int main () 30 { 31 int m; 32 while (scanf ("%d %d", &n, &m) != EOF) 33 { 34 G.clear(); 35 G.resize(n+1);//动态申请空间 36 while (m --) 37 { 38 int a, b, s; 39 scanf ("%d %d %d", &a, &b, &s); 40 G[a].push_back(Edge(b, s)); 41 } 42 dijkstra (); 43 } 44 return 0; 45 } 46 47 void dijkstra() 48 { 49 priority_queue<Edge>Q; 50 Edge p, q; 51 memset (vis, false, sizeof(vis)); 52 p.e = 1, p.w = 0; 53 Q.push (p); 54 55 while (!Q.empty()) 56 { 57 p = Q.top();//选取最优点 58 Q.pop(); 59 if (vis[p.e])//已求出最短路,进行下一个 60 continue; 61 62 if (p.e == n)//已求出1到n的最短路 63 break; 64 vis[p.e] = true; 65 int len = G[p.e].size(); 66 67 for (int i=0; i<len; i++) 68 { 69 q = G[p.e][i]; 70 if ( !vis[q.e] )//对剩余的点进行松弛操作 71 { 72 q.w += p.w; 73 Q.push(q); 74 } 75 } 76 } 77 printf ("%d\n", p.w); 78 }