1. 程式人生 > >CF 360E Levko and Game——貪心

CF 360E Levko and Game——貪心

題目:http://codeforces.com/contest/360/problem/E

官方題解與證明:http://codeforces.com/blog/entry/9529

一條可以調整的邊的邊權要麼是 l [ i ] 要麼是 r[ i ] 。

先把所有可調整邊設成 r[ i ] ,然後看看有沒有一條可調整的邊 (x,y)滿足 dis1[x]<=dis2[x] 且其邊權還是 r[ i ];如果有,就把它改成 l [ i ]。

改完一條邊之後就再做一遍 dij( ) ,然後再改;直到沒有可改的邊。

其實每次可以不止改一條邊,可以把能改的邊都改了。因為據證明,一條邊 (x,y) 如果 dis1[x]<=dis2[x] ,不會在之後某次修改別的邊的時候變成 dis1[x]>dis2[x] 了;所以一旦能改,就一直能改,所以一次改很多能改的邊也是可以的。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
using namespace std;
const int N=1e4+5,M=105;
int n,m,t,hd[N],xnt,bh[M],l[M],r[M],s1,s2,F;
ll dis1[N],dis2[N];bool vis[N],ans[M];
priority_queue<pair<ll,int> > q;
struct
Ed{ int x,to,nxt,w; Ed(int f=0,int a=0,int b=0,int c=0):x(f),to(a),nxt(b),w(c) {} }ed[N+M]; int rdn() { int ret=0;bool fx=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();} while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar(); return fx?ret:-ret; } void
add(int x,int y,int z){ed[++xnt]=Ed(x,y,hd[x],z);hd[x]=xnt;} void dj() { memset(dis1,0x3f,sizeof dis1);dis1[s1]=0; memset(vis,0,sizeof vis); q.push(make_pair(0,s1)); while(q.size()) { int k=q.top().second;q.pop(); if(vis[k])continue;vis[k]=1; for(int i=hd[k],v;i;i=ed[i].nxt) if(dis1[v=ed[i].to]>dis1[k]+ed[i].w) dis1[v]=dis1[k]+ed[i].w,q.push(make_pair(-dis1[v],v)); } memset(dis2,0x3f,sizeof dis2);dis2[s2]=0; memset(vis,0,sizeof vis); q.push(make_pair(0,s2)); while(q.size()) { int k=q.top().second;q.pop(); if(vis[k])continue;vis[k]=1; for(int i=hd[k],v;i;i=ed[i].nxt) if(dis2[v=ed[i].to]>dis2[k]+ed[i].w) dis2[v]=dis2[k]+ed[i].w,q.push(make_pair(-dis2[v],v)); } } int main() { n=rdn();m=rdn();t=rdn(); s1=rdn();s2=rdn();F=rdn(); for(int i=1,u,v,z;i<=m;i++) u=rdn(),v=rdn(),z=rdn(),add(u,v,z); for(int i=1,u,v;i<=t;i++) { u=rdn();v=rdn();l[i]=rdn();r[i]=rdn(); add(u,v,r[i]); bh[i]=xnt; } bool flag; while(1) { dj();flag=0; for(int i=1,d;i<=t;i++) { d=bh[i]; if(ed[d].w==l[i]||dis1[ed[d].x]>dis2[ed[d].x])continue; ed[d].w=l[i];ans[i]=1;flag=1; } if(!flag)break; } dj(); if(dis1[F]>dis2[F]){puts("LOSE");return 0;} if(dis1[F]==dis2[F])puts("DRAW"); else puts("WIN"); for(int i=1;i<=t;i++)printf("%d ",ans[i]?l[i]:r[i]);puts(""); return 0; }