题目传送门(内部题115)
输入格式
第一行两个正整数$n,m$。
接下来$m$行,每行$4$个正整数$u_j,v_j,L_j,R_j$。
接下来一行$n$个数,若第$i$个数为$1$,则$i$号同学最后学会了毒瘤算法;若第$i$个数为$-1$,则$i$号同学最后没有学会毒瘤算法。若第$i$个数为$0$,则不知道$i$号同学最后是否学会了毒瘤算法。
输出格式
若结果不可能出现,输出一行$Impossible$;否则,输出$m$行,第$j$行一个正整数表示第$j$条信息中的两名同学在哪一天共用午餐。
样例
样例输入1:
4 3
1 2 1 2
2 3 1 2
2 4 1 2
1 0 1 -1
样例输出1:
2
2
1
样例输入2:
4 4
1 2 1 2
2 3 2 3
2 4 1 2
3 4 3 4
1 0 1 -1
样例输出2:
Impossible
数据范围与提示
本题采用子任务评分。仅当你通过一个子任务下所有测试点时,你才能获得该子任务的分数。
对于所有数据,$1\leqslant n,m\leqslant 200,000,1\leqslant u_j,v_j\leqslant n,u_j\neq v_j,1\leqslant L_i\leqslant R_i\leqslant 10^9$。
$1.$($10$分)$n,m\leqslant 12,R_i\leqslant 3$。
$2.$($15$分)$m=n-1$,且共用午餐的关系将所有同学连接到了一起。
$3.$($15$分)不存在确定没有学会毒瘤算法的同学。
$4.$($20$分)$n,m\leqslant 2,000$。
$5.$($40$分)没有特殊限制。
题解
在没有限制的情况下(不存在确定没有学会毒瘤算法的同学),显然贪心的选择最早学更优。
那么现在我们考虑有没有学会毒瘤算法的同学的情况。
不妨设$sec[i]$表示$i$点最早学会毒瘤算法的时间,那么没有学会毒瘤算法的同学付成$inf$即可。
对于一个转移向这个同学的同学,其$sec$即为这条转移边的$l+1$,因为这两名同学可以在$l$时刻吃饭。
这个过程可以用类似最短路的思想解决。
剩余情况下尽可能早的吃饭一定更优,注意边界即可。
时间复杂度:$\Theta(n\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h> using namespace std; struct rec{int nxt,to,l,r;}e[400001]; struct node{int x,y,l,r;}b[200001]; int head[200001],cnt; int n,m; int a[200001]; int sec[200001],dis[200001]; bool vis[200001]; priority_queue<pair<int,int>>qs; priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>qt; void add(int x,int y,int l,int r){e[++cnt]=(rec){head[x],y,l,r};head[x]=cnt;} void Dij() { while(qs.size()) { int x=qs.top().second; qs.pop(); if(vis[x])continue; vis[x]=1; for(int i=head[x];i;i=e[i].nxt) { if(e[i].r<sec[x]&&sec[e[i].to]<=e[i].l) { sec[e[i].to]=e[i].l+1; qs.push(make_pair(sec[e[i].to],e[i].to)); } } } } void DIJ() { memset(dis,0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); qt.push(make_pair(0,1)); dis[1]=0; while(qt.size()) { int x=qt.top().second; qt.pop(); if(vis[x])continue; vis[x]=1; for(int i=head[x];i;i=e[i].nxt) { int maxn=max(max(sec[e[i].to],e[i].l),dis[x]); if(maxn<dis[e[i].to]&&maxn<=e[i].r) { dis[e[i].to]=maxn; qt.push(make_pair(dis[e[i].to],e[i].to)); } } } } int main() { freopen("lunch.in","r",stdin); freopen("lunch.out","w",stdout); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&b[i].x,&b[i].y,&b[i].l,&b[i].r); add(b[i].x,b[i].y,b[i].l,b[i].r); add(b[i].y,b[i].x,b[i].l,b[i].r); } for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(a[i]==-1) { sec[i]=0x3f3f3f3f; qs.push(make_pair(0x3f3f3f3f,i)); } } Dij(); DIJ(); for(int i=1;i<=n;i++)if(a[i]==1&&dis[i]==0x3f3f3f3f){puts("Impossible");return 0;} for(int i=1;i<=m;i++) { if(a[b[i].x]==-1&&dis[b[i].y]<=b[i].l){puts("Impossible");return 0;} if(a[b[i].y]==-1&&dis[b[i].x]<=b[i].l){puts("Impossible");return 0;} } for(int i=1;i<=m;i++) { if(a[b[i].x]==-1||a[b[i].y]==-1||b[i].r<max(dis[b[i].x],dis[b[i].y]))printf("%d\n",b[i].l); else printf("%d\n",max(b[i].l,max(dis[b[i].x],dis[b[i].y]))); } return 0; }
rp++