差分约束
题意倒是简单,难的是建立约束(建边)。可以初始化INF求最小,然后输出-dis[maxn]。也可以初始化-INF求最大,输出dis[maxn]。
求最大的时候:
minn为最小,maxn为最大。
输入 u ,v len 建立约束为 u->v = len,最后在 minn和maxn之间还要建立 i->i-1=-1 , i-1->i=0。
最后求minn-1 ~maxn 的最大距离。
求最小就是 建边不变,距离变负。
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<stack> #include<iostream> #include<list> #include<set> #include<cmath> #define INF 0x7fffffff #define eps 1e-6 #define LL long long using namespace std; int n,maxn,minn,m; struct lx { int v,len; }; vector<lx>g[51001]; queue<int>q; void SPFA() { bool vis[51001]; int dis[51001]; for(int i=0;i<=maxn;i++) vis[i]=0,dis[i]=-INF; vis[minn-1]=1,dis[minn-1]=0; q.push(minn-1); while(!q.empty()) { int u=q.front();q.pop(); vis[u]=0; for(int j=0;j<g[u].size();j++) { int v=g[u][j].v; int len=g[u][j].len; // printf("v=%d,u=%d:%d>%d+%d=\n",v,u,dis[v],dis[u],len); // system("pause"); if(dis[v]<dis[u]+len) { dis[v]=dis[u]+len; if(!vis[v]) { vis[v]=1; q.push(v); } } } } printf("%d\n",dis[maxn]); // for(int i=minn-1;i<=maxn;i++) // printf("%d : %d ==\n",i,dis[i]); } int main() { while(scanf("%d",&m)!=EOF) { minn=INF,maxn=0; for(int i=0;i<51001;i++) g[i].clear(); int u,v,len; lx now; while(m--) { scanf("%d%d%d",&u,&v,&len); maxn=max(maxn,v); minn=min(minn,u); now.v=v,now.len=len; g[u-1].push_back(now); } for(int i=minn;i<=maxn;i++) { now.v=i-1,now.len=-1; g[i].push_back(now); now.v=i,now.len=0; g[i-1].push_back(now); } // for(int i=minn-1;i<=maxn;i++) // { // printf("%d-> ",i); // for(int j=0;j<g[i].size();j++) // printf("%d:%d ",g[i][j].v,g[i][j].len); // printf("\n"); // } while(!q.empty())q.pop(); SPFA(); } }
原文:http://blog.csdn.net/dongshimou/article/details/38021433