差分约束系统
例如,
5 6
20 34 54 10 15
这一组测试数据
先编号,分别为1 2 3 4 5 ,然后可以写出一组表达式,两个编号之间的距离必定大于等于1的,所以i+1到i建立有向边,权值为-1,然后进行结构体排序,根据高度来排序。然后相邻两个节点再写表达式,标号小的到标号大的之间建立有向边,权值为D,最后把高度最小的编号和高度最大的编号找出来,因为要求的是最大值,所以采用最短路来解决。把高度最小的编号设置为起点,求出到高度最大的编号的最短路,就是答案。如果存在环,就输出-1。
#include<cstdio> #include<cstring> #include<cmath> #include<vector> #include<queue> #include<algorithm> using namespace std; const int maxn=1111; const int INF=0x7FFFFFFF; struct HH {int id,heights;}node[maxn]; struct abc {int startt,endd,costt;}dd[2*maxn]; bool cmp(const HH&a,const HH&b){return a.heights<b.heights;} vector<abc>ljb[maxn]; int ff[maxn],summ[maxn],dist[maxn]; int n,h,D,ss,ee,qd,zd; int tyu; void spfa() { queue<int>Q; while(!Q.empty()) Q.pop(); int i; for(i=0; i<=n; i++) dist[i]=INF; memset(ff,0,sizeof(ff)); memset(summ,0,sizeof(summ)); dist[qd]=0; ff[qd]=1; Q.push(qd); while(!Q.empty()) { int hh=Q.front(); Q.pop(); summ[hh]++; if(summ[hh]>n){tyu=1;break;} ff[hh]=0; for(i=0; i<ljb[hh].size(); i++) { abc noww; noww=ljb[hh][i]; if(dist[hh]+noww.costt<dist[noww.endd]) { dist[noww.endd]=dist[hh]+noww.costt; if(ff[noww.endd]==0) { ff[noww.endd]=1; Q.push(noww.endd); } } } } } int main() { int T,t; scanf("%d",&T); for(t=1;t<=T;t++) { int i; scanf("%d%d",&n,&D); for(i=0;i<=n;i++) ljb[i].clear(); for(i=0;i<n;i++) { scanf("%d",&h); node[i].id=i+1; node[i].heights=h; } int tott=0; for(i=0;i<n-1;i++) { dd[tott].startt=node[i+1].id; dd[tott].endd=node[i].id; dd[tott].costt=-1; ljb[node[i+1].id].push_back(dd[tott]); tott++; } sort(node,node+n,cmp); ss=node[0].id; ee=node[n-1].id; if(ss>ee) qd=ee,zd=ss; else qd=ss,zd=ee; for(i=0;i<n-1;i++) { if(node[i].id>node[i+1].id) { dd[tott].startt=node[i+1].id; dd[tott].endd=node[i].id; dd[tott].costt=D; ljb[node[i+1].id].push_back(dd[tott]); tott++; } else if(node[i].id<node[i+1].id) { dd[tott].startt=node[i].id; dd[tott].endd=node[i+1].id; dd[tott].costt=D; ljb[node[i].id].push_back(dd[tott]); tott++; } } tyu=0; spfa(); printf("Case %d: ",t); if(tyu==0)printf("%d ",dist[zd]-dist[qd]); else printf("-1 "); } return 0; }