POJ 3169 Layout 【差分约束】+【spfa】
<题目链接>
题目大意:
一些母牛按序号排成一条直线。有两种要求,A和B距离不得超过X,还有一种是C和D距离不得少于Y,问可能的最大距离。如果没有最大距离输出-1,如果1、n之间距离任意就输出-2,否则输出最大的距离。
解题分析:
典型的差分约束,第一种约束,v-u<=c;第二种约束:v-u>=c 可以转化为 u-v<=c ,还有一种约束,因为题目要求按序号排序,所以 loc[i] - loc[i-1]>=0 ,即 loc[i-1]-loc[i]<=0 。以上就是本题的三种约束,利用上述三种约束建图,然后跑一遍最短路即可,因为可能存在负权边,所以用spfa求解。当该图存在负环的时候输出-1,当1~n不连通的时候输出-2,否则输出1---->n的最短边权约束和。即所求的最大距离。
1 #include <cstdio> 2 #include <cstring> 3 #include <queue> 4 #include <algorithm> 5 using namespace std; 6 7 const int N =1e3+10; 8 const int M =2e5+10; 9 #define INF 0x3f3f3f3f 10 struct EDGE{ 11 int to,val,next; 12 }edge[M]; 13 int head[N],dis[N],cnt[N],tot,n,ml,md; 14 bool vis[N]; 15 16 void init(){ 17 memset(head,-1,sizeof(head)); 18 tot=0; 19 } 20 void add(int u,int v,int w){ 21 edge[++tot].to=v,edge[tot].val=w; 22 edge[tot].next=head[u],head[u]=tot; 23 } 24 int spfa(int s){ //因为存在负权边,所以用spfa求最短路 25 memset(dis,INF,sizeof(dis)); 26 memset(vis,false,sizeof(vis)); 27 memset(cnt,0,sizeof(cnt)); 28 queue<int>q; 29 q.push(s); 30 vis[s]=true,cnt[s]=1,dis[s]=0; 31 while(!q.empty()){ 32 int cur=q.front(); 33 q.pop(); 34 vis[cur]=false; 35 for(int i=head[cur];~i;i=edge[i].next){ 36 int v=edge[i].to; 37 if(dis[v]>dis[cur]+edge[i].val){ 38 dis[v]=dis[cur]+edge[i].val; 39 if(!vis[v]){ 40 vis[v]=true; 41 if(++cnt[v]>n)return -1; //进队列次数>n,说明存在负环,直接返回-1 42 q.push(v); 43 } 44 } 45 } 46 } 47 if(dis[n]==INF)return -2; //如果两点不连通,说明1、n两点之间没有约束条件,所以1、n可以距离任意远,返回-2 48 return dis[n]; 49 } 50 int main(){ 51 while(scanf("%d%d%d",&n,&ml,&md)!=EOF){ 52 init(); 53 for(int i=1;i<=n;i++)add(i,i-1,0); //代表s[i-1]-s[i]<=0 54 for(int i=1;i<=ml;i++){ 55 int u,v,c;scanf("%d%d%d",&u,&v,&c); 56 add(u,v,c); //v-u<=c 57 } 58 for(int i=1;i<=md;i++){ 59 int u,v,c;scanf("%d%d%d",&u,&v,&c); 60 add(v,u,-c); //u-v<=-c,即v-u>=c 61 } 62 //利用题目条件,整合成三个差分约束条件,利用这几个条件建图,然后跑一遍最短路 63 printf("%d\n",spfa(1)); 64 } 65 }
2018-10-11
作者:is_ok
出处:http://www.cnblogs.com/00isok/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。