原題地址:http://poj.org/problem?id=3159算法
題意大概是班長髮糖果,班裏面有不良風氣,A但願B的糖果不比本身多C個。班長要知足小朋友的需求,並且要讓本身的糖果比snoopy的儘可能多。oop
好比如今ABCD四個小朋友,B的糖果不能超過A的5個,若是A的史努比,D是班長,那麼班長最多比史努比多7個糖果,而不是5+4+1=9個。優化
由於若是是9個,就不知足D-A<=(D-C)+(C-A)<=7的條件。spa
不懂的能夠翻一下算法導論,上面有差分約束的定義和證實,總之這是一個求最短路的問題==。3d
其實爲了理解題意,我也花了好久時間SF-_-。code
知道是求最短路以後,作法就有不少了,BUT數據量較大,不少作法會超時。這裏推薦兩個算法,一個是優先隊列優化的Dijkstra算法,AC代碼以下(579MS):blog
#include <cstdio> #include <vector> #include <queue> #include <cstring> using namespace std; struct CNode { int k; int w; bool operator<(const CNode& cmp) const { return w>cmp.w; } }; priority_queue<CNode> pq; bool vis[30030]; int first[30030],vv[150010],ww[150010],nxt[150010]; const int inf=~(1<<31); CNode p,q; int main() { // freopen("in.txt","r",stdin); memset(d,0,sizeof(d)); int e=2; int n,m,u,v,w; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&w); nxt[e]=first[u],vv[e]=v,ww[e]=w,first[u]=e++; } p.k=1; p.w=0; pq.push(p); while(!pq.empty()) { p=pq.top(); pq.pop(); if(vis[p.k]) continue; vis[p.k]=true; if(p.k==n) break; for(int e=first[p.k];e;e=nxt[e]) if(!vis[vv[e]]) { q.k=vv[e]; q.w=p.w+ww[e]; pq.push(q); } } printf("%d\n",p.w); }
另外一個是棧優化的SPFA算法(532MS):隊列
#include <cstdio> #include <vector> #include <queue> #include <cstring> using namespace std; int d[30030]; int stack[30030]; bool vis[30030]; int first[30030],vv[150010],ww[150010],nxt[150010]; const int inf=~(1<<31); int main() { // freopen("in.txt","r",stdin); memset(d,0,sizeof(d)); int e=2; int n,m,u,v,w; scanf("%d%d",&n,&m); for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&w); nxt[e]=first[u],vv[e]=v,ww[e]=w,first[u]=e++; } memset(d,0x7f,sizeof(d)); int top=0; stack[++top]=1; vis[1]=true; d[1]=0; while(top) { int a=stack[top--]; vis[a]=false; for(int e=first[a];e;e=nxt[e]) if(d[vv[e]]>ww[e]+d[a]) { d[vv[e]]=ww[e]+d[a]; if(!vis[vv[e]]) { stack[++top]=vv[e]; vis[vv[e]]=true; } } } printf("%d\n",d[n]); }