查分约束的转移建图好题!!!
题意:给出n个人,ml个两人之间的最远约束,md个两个人之间的最近约束,求最远的两个人的距离。
解题思路:查分约束,题目要求最大值,那么将不等式都变为<=的形式,然后求最短路
设d[i]为i到最左边的人的距离,由于题目附加条件是
d[I+1]-d[I]>=0 (我们转化为 d[I]-d[I+1]<=0)
即最左边的人一定是1;
输入最远约束时
d[a]-d[b]<=c, 建图a->b=c;
输入最近约束时
d[b]-d[a]<=-c 建图b->a=-c;
隐含条件建图时
d[I]-d[I+1]<=0,建图(i+1)->(i)=0;
如果有负环,说明无满足要求的排法,输出-1
如果图不连通,说明两个不连通图之间的人可以任意排,输出-2
其它,输出DIS[N]
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #include<queue> using namespace std; const int INF = 1<<26; struct node{ int y,w,next; }edge[150005]; int dis[10010],n,m1,edgeHead[10010],stack[100010],m2,cot[10010]; bool vis[10010]; bool spfa(){//下表为1开始 for(int i = 2; i <= n; i ++) { dis[i] = INF; cot[i] = 0; } dis[1] = 0; int top = 0; // spfa的堆栈实现模板。 stack[++ top] = 1; vis[1] = true; while(top){ int x = stack[top --]; cot[x]++; if(cot[x]>n) return false; for(int p = edgeHead[x]; p != 0; p = edge[p].next){ int y = edge[p].y; if(dis[y] > dis[x] + edge[p].w){ dis[y] = dis[x] + edge[p].w; if(!vis[y]){ vis[y] = true; stack[++ top] = y; } } } vis[x] = false; } return true; } int main() { int i,j,t; int x,y,v,k=1; scanf("%d",&t); while(t--) { scanf("%d %d %d",&n,&m1,&m2); for(i=1;i<=n;i++) { edge[i].next=0; edgeHead[i]=0; } for(i=1;i<=m1;i++)//d[y]-d[x]<=c { scanf("%d %d %d",&x,&y,&v); edge[k].y=y; edge[k].w=v; edge[k].next=edgeHead[x]; edgeHead[x]=k++; } for(i=1;i<=m2;i++)//d[y]-d[x]>=c => d[x]-d[y]<=-c { scanf("%d %d %d",&x,&y,&v); edge[k].y=x; edge[k].w=-v; edge[k].next=edgeHead[y]; edgeHead[y]=k++; } for(i=1;i<=n;i++) { edge[k].y=i; edge[k].w=0; edge[k].next=edgeHead[i+1]; edgeHead[i+1]=k++; } int ans; if(!spfa()) ans = -1; else if(dis[n] == INF) ans = -2; else ans=dis[n]; printf("%d\n",ans); } return 0; }