HDU 2017中國大學生程式設計競賽-總決賽 Subway Chasing [差分約束]
阿新 • • 發佈:2018-12-22
題意:我與朋友要從1走到n,朋友比我先x分鐘走,然後給出m個事件,每個事件給出我的與朋友的位置,求符合這些事件的相鄰的點的距離。
題解:可以看出每個事件可以給出2種情況:
①a==b&&c==d 那麼我們能得到差分條件:c-a<=x a-c<=-x
②a-d<=-(x+1) c-b<=x-1
然後約束一下相鄰點的距離要大於1
for(int i=2;i<=n;i++)
AddEdges(i-1,i,-1);
跑差分約束得到的Dist,相鄰Dist相減就是答案。
AC程式碼:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> #define INF 0x7fffffff using namespace std; const int MAXN = 2005; const int MAXM = 30030; struct EdgeNode { int to; int w; int next; }Edges[MAXM]; int Head[MAXN],Dist[MAXN],vis[MAXN],outque[MAXN],id; void AddEdges(int u,int v,int w) { Edges[id].to = v; Edges[id].w = w; Edges[id].next = Head[u]; Head[u] = id++; } void SPFA(int s,int N) { int ans = 0; memset(vis,0,sizeof(vis)); memset(outque,0,sizeof(outque)); for(int i = 1; i <= N; ++i) Dist[i] = INF; Dist[s] = 0; vis[s] = 1; queue<int> Q; Q.push(s); while( !Q.empty() ) { int u = Q.front(); Q.pop(); vis[u] = 0; outque[u]++; if(outque[u] > N+1) //如果出隊次數大於N,則說明出現負環 { ans = -1; break; } for(int i = Head[u]; i != -1; i = Edges[i].next) { int temp = Dist[u] + Edges[i].w; if(temp < Dist[Edges[i].to]) { Dist[Edges[i].to] = temp; if( !vis[Edges[i].to]) { vis[Edges[i].to] = 1; Q.push(Edges[i].to); } } } } if(ans == -1) //出現負權迴路,不存在可行解 printf("IMPOSSIBLE\n"); else { for(int i=2;i<=N;i++) printf(" %d",Dist[i-1]-Dist[i]); printf("\n"); } } int main() { int T; scanf("%d",&T); int cas=1; while(T--) { memset(Head,-1,sizeof(Head)); id = 0; int n,m,x; scanf("%d%d%d",&n,&m,&x); for(int i=2;i<=n;i++) AddEdges(i-1,i,-1); for(int i=0;i<m;i++) { int a,b,c,d; scanf("%d%d%d%d",&a,&b,&c,&d); if(a==b&&c==d) { AddEdges(c,a,x); AddEdges(a,c,-x); } else { AddEdges(a,d,-(x+1)); AddEdges(c,b,x-1); } } printf("Case #%d:",cas++); SPFA(1,n); } return 0; }