题目:http://codeforces.com/contest/360/problem/E
首先,每条边不是选 \( l[i] \) 就是选 \( r[i] \);
做法就是先把边权都设成 \( r[i] \),然后做 \( dijkstra \),如果有一条可改的边 \( (a,b) \) 而且 \( dis1[a] < dis2[a] \),那么就改边权为 \( l[i] \);
然后重复这个过程直到无边可改;
因为要考虑平局,所以只要 \( dis1[a] <= dis2[a] \) 就改,这样先让第一个人的路是最优的;
其实也不用一条一条改,一次改所有能改的就行,因为据题解的证明,一次改了一条边后,不会使一个 \( dis1[a] <= dis2[a] \) 的边突然变得 \( dis1[a] > dis2[a] \)
题解的证明...看不动了...感性理解...
代码如下:
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; typedef long long ll; int const xn=1e4+105,xm=105; int n,m,cnt,hd[xn],ct,to[xn],nxt[xn],w[xn],s1,s2,f; ll dis[2][xn],inf=1e17; bool vis[xn]; struct E{int u,v,bh,l,r,w;}ed[xm]; struct N{ ll d; int id; N(ll d=0,int i=0):d(d),id(i) {} bool operator < (const N &y) const {return d>y.d;} }; priority_queue<N>q; int rd() { int ret=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return f?ret:-ret; } void add(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; w[ct]=z;} void dij(int t) { for(int i=1;i<=n;i++)dis[t][i]=inf; for(int i=1;i<=n;i++)vis[i]=0; int st=(t?s2:s1); dis[t][st]=0; q.push(N(0,st)); while(q.size()) { int x=q.top().id; q.pop(); if(vis[x])continue; vis[x]=1; for(int i=hd[x],u;i;i=nxt[i]) if(dis[t][u=to[i]]>dis[t][x]+w[i]) { dis[t][u]=dis[t][x]+w[i]; q.push(N(dis[t][u],u)); } } } int main() { n=rd(); m=rd(); cnt=rd(); s1=rd(); s2=rd(); f=rd(); for(int i=1,x,y,z;i<=m;i++)x=rd(),y=rd(),z=rd(),add(x,y,z); for(int i=1;i<=cnt;i++) ed[i].u=rd(),ed[i].v=rd(),ed[i].l=rd(),ed[i].r=rd(), ed[i].bh=ct+1,ed[i].w=1,add(ed[i].u,ed[i].v,ed[i].r); dij(0); dij(1); while(dis[0][f]>=dis[1][f]) { int i; for(i=1;i<=cnt;i++) if(dis[0][ed[i].u]<=dis[1][ed[i].u]&&ed[i].w)break; if(i>cnt) { if(dis[0][f]>dis[1][f])puts("LOSE"); else { puts("DRAW"); for(int j=1;j<=cnt;j++)printf("%d ",ed[j].w?ed[j].r:ed[j].l); puts(""); } return 0; } ed[i].w=0; w[ed[i].bh]=ed[i].l; dij(0); dij(1); } puts("WIN"); for(int j=1;j<=cnt;j++)printf("%d ",ed[j].w?ed[j].r:ed[j].l); puts(""); return 0; }