考场真是什么也没想出来
暴力都没打对,真是没救了
还好我现在稍微会了一点
有一个奇怪的子任务:不存在确定没有学会毒瘤算法的同学。
看上去这个子任务给的性质好像没什么用
我们还是可以推一推
贪心取L即可
证明感性理解一下
于是f[x]=min(f[x],L)
最短路形式,可以用最短路转移
然后将这个子任务推广
如果存在没有学会毒瘤算法的同学就是相当于给上述转移加了一个限制条件
例如
现有wwb,whs二人
已知wwb学习毒瘤算法时间在>R,那么就意味着这次吃饭时whs也不会毒瘤算法
仍然贪心考虑
whs和wwb二人吃饭于L,然后whs在L+1学会毒瘤算法,就满足限制了
于是lim[x]=max(L+1)
先把lim算出来,再转移f就可以了
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1111111 ll n,m,tot; ll vis[A],mn[A],mx[A],head[A],nxt[A],ver[A],dis[A],flag[A],lst[A],lim[A]; struct node{ ll x,y,l,r; node(){} node(const ll &a,const ll &b,const ll &c,const ll &d){x=a,y=b,l=c,r=d;} }u[A]; void add(ll x,ll y,ll minn,ll maxx){ nxt[++tot]=head[x],ver[tot]=y,head[x]=tot,mn[tot]=minn,mx[tot]=maxx; } void pre_spfa(){ deque<ll> q; for(ll i=1;i<=n;i++){ scanf("%lld",&lst[i]); if(lst[i]==-1) lim[i]=1e9+7,vis[i]=1,q.push_back(i); else vis[i]=0; } while(!q.empty()){ ll x=q.front();q.pop_front(); vis[x]=0; for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i],minn=mn[i],maxx=mx[i]; if(lim[x]>maxx){ if(lim[y]<minn+1){ lim[y]=minn+1; if(!vis[y]){ vis[y]=1; q.push_back(y); } } } } } } void spfa(){ deque<ll> q; for(ll i=1;i<=n;i++) vis[i]=0,dis[i]=1e9+7; dis[1]=0;q.push_back(1); while(!q.empty()){ ll x=q.front();q.pop_front(); vis[x]=0; for(ll i=head[x];i;i=nxt[i]){ ll y=ver[i],minn=mn[i],maxx=mx[i],g=max(max(lim[y],minn),dis[x]); // printf("y=%lld minn=%lld maxx=%lld g=%lld\n",y,minn,maxx,g); if(dis[y]>g&&g<=maxx){ dis[y]=g; // printf("dis[%lld]=%lld\n",y,dis[y]); if(!vis[y]){ vis[y]=1; q.push_back(y); } } } } } int main(){ freopen("lunch.in","r",stdin); freopen("lunch.out","w",stdout); scanf("%lld%lld",&n,&m); for(ll i=1;i<=m;i++){ ll x,y,a,b; scanf("%lld%lld%lld%lld",&x,&y,&a,&b); add(x,y,a,b); add(y,x,a,b); u[i]=node(x,y,a,b); } pre_spfa(); spfa(); for(ll i=1;i<=n;i++) if(lst[i]==1&&dis[i]>1e9){ puts("Impossible\n"); return 0; } for(ll i=1;i<=m;i++){ ll x=u[i].x,y=u[i].y; if(lst[x]==-1&&dis[y]<u[i].l){ puts("Impossible\n"); return 0; } if(lst[y]==-1&&dis[x]<u[i].l){ puts("Impossible\n"); return 0; } } // for(ll i=1;i<=n;i++) // printf("lim=%lld dis=%lld\n",lim[i],dis[i]); for(ll i=1;i<=m;i++){ ll x=u[i].x,y=u[i].y; if(lst[x]==-1||lst[y]==-1) printf("%lld\n",u[i].l); else printf("%lld\n",max(dis[x],dis[y])>u[i].r?u[i].l:max(u[i].l,max(dis[x],dis[y]))); } }