[noip模拟赛]午餐
https://www.zybuluo.com/ysner/note/1325779
题面
一共有\(n\)个人,林先森知道开始时只有\(1\)号会毒瘤算法。林先森了解到很多人一起吃过
午餐;具体地,有\(m\)条信息,其中第\(j\)条信息描述\(u_j\)和\(v_j\)在\([L_j,R_j]\)区间中的某一天一起吃
了午餐。若此时\(u_j\)或\(v_j\)中的一个人会毒瘤算法,那么两个人都能学会毒瘤算法。特别地,若
一个人在某天和多个人一起吃午餐,那么他在学会毒瘤算法的同时会立即教给别人(同一天的
午餐均视作同时发生)。
林先森知道最后学会了毒瘤算法的同学以及没有学会毒瘤算法的同学,以及一些不确定是
否学会了毒瘤算法的同学。林先森想知道大家具体在哪一天共用了午餐,或者告诉林先森这样
的结果是不可能出现的。
- \(10pts\) \(n,m\leq12,R_i\leq3\)
- \(45pts\) 不存在确定没有学会毒瘤算法的同学
- \(100pts\ n,m\leq2*10^5\)
解析
做难题从部分分开始。
\(45pts\)算法
显然,如果有这条性质,可以推个贪心结论:每个人尽早学会毒瘤算法肯定是最优的。
所以可以设\(f[i]\)表示第\(i\)个人最早学会毒瘤算法的时间。
\(f[v]=\max(f[u],L)\)
然后发现转移等价于最短路。
那么拿\(Dijstra\)跑一跑就行。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define re register
#define il inline
#define pi pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define fp(i,a,b) for(re int i=a;i<=b;++i)
#define fq(i,a,b) for(re int i=a;i>=b;--i)
using namespace std;
const int N=20,M=2e5+100;
int n,m,cho[N],tar[M],top[N],mx,tag=1;
struct dat{int u,v,L,R;}a[M],sta[10][N];
bool vis[M];
int h[M],cnt,dis[M];
struct Edge{int to,nxt,mn,mx;}e[M<<1];
il void add(re int u,re int v,re int mn,re int mx)
{
e[++cnt]=(Edge){v,h[u],mn,mx};h[u]=cnt;
e[++cnt]=(Edge){u,h[v],mn,mx};h[v]=cnt;
}
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il void out()
{
fp(i,1,m) printf("%d\n",cho[i]);
exit(0);
}
il void check()
{
fp(i,1,n) vis[i]=0;vis[1]=1;
fp(i,1,mx)
{
fp(j,1,top[i]) if(vis[sta[i][j].u]||vis[sta[i][j].v]) vis[sta[i][j].u]=vis[sta[i][j].v]=1;
fp(j,1,top[i]) if(vis[sta[i][j].u]||vis[sta[i][j].v]) vis[sta[i][j].u]=vis[sta[i][j].v]=1;
}
re int tag=1;
fp(i,1,n) if((tar[i]==1&&!vis[i])||(tar[i]==-1&&vis[i])) {tag=0;break;}
if(tag) out();
}
il void dfs(re int x)
{
if(x>m) {check();return;}
fp(i,a[x].L,a[x].R)
{
mx=max(mx,a[x].R);
cho[x]=i;
sta[i][++top[i]]=a[x];
dfs(x+1);
--top[i];
}
}
il int min(re int x,re int y){return x<y?x:y;}
il int max(re int x,re int y){return x>y?x:y;}
il void Dijstra()
{
priority_queue<pi,vector<pi>,greater<pi> >Q;
while(!Q.empty()) Q.pop();
fp(i,1,n) vis[i]=0,dis[i]=1e9+7;
dis[1]=0;Q.push(mk(0,1));
while(!Q.empty())
{
re int u=Q.top().se;Q.pop();
vis[u]=1;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to,mx=e[i].mx,mn=e[i].mn;
if(dis[v]>max(mn,dis[u])&&dis[u]<=mx)
{
dis[v]=max(mn,dis[u]);
Q.push(mk(dis[v],v));
}
}
while(!Q.empty()&&vis[Q.top().se]) Q.pop();
}
}
il void solve()
{
memset(h,-1,sizeof(h));
fp(i,1,m) add(a[i].u,a[i].v,a[i].L,a[i].R);
Dijstra();
fp(i,1,n) if(tar[i]==1&&dis[i]>1e9) {puts("Impossible");exit(0);}
fp(i,1,m) printf("%d\n",dis[a[i].u]>a[i].R?a[i].L:max(a[i].L,dis[a[i].u]));
exit(0);
}
int main()
{
n=gi();m=gi();
fp(i,1,m)
{
a[i].u=gi(),a[i].v=gi(),a[i].L=gi(),a[i].R=gi();
}
fp(i,1,n) tar[i]=gi(),tag&=(tar[i]>=0);
if(n>12&&tag) solve();//for ex35pts
dfs(1);//for 10pts
puts("Impossible");
return 0;
}
\(100pts\)算法
直接想\(100pts\)是有难度的。
但有\(45pts\)作为铺垫就比较好想了。
如果有确定没学会的人,相当于给他周围的人(与他吃饭的人)的\(f[i]\)的下限\(lim[i]\)。
因为他们吃饭的时间一定在\(L_i\),然后\(f[i]\)就必须大于\(L_i\),即下限为\(L_i+1\)。
(接下来这点自己没想到)
然后这个下限的影响是可以扩散的。
设一个人为\(u\),和他吃饭的某人为\(v\)。
如果\(f[u]>R\),就说明\(v\)不能给\(u\)传授算法,那么他们吃饭时\(v\)不应该会算法。
为保证\(f[v]\)最小,吃饭时间一定为\(L\),则\(lim[v]\geq L+1\)。
这个过程可以用最短路维护。
在此基础上,贪心显然仍成立。
那么接着最短路转移\(f[i]\),过程中保证\(f[i]\geq lim[i]\)即可。
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define ll long long
#define re register
#define il inline
#define pi pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define fp(i,a,b) for(re int i=a;i<=b;++i)
#define fq(i,a,b) for(re int i=a;i>=b;--i)
using namespace std;
const int M=2e5+100;
int n,m,tar[M],lim[M];
struct dat{int u,v,L,R;}a[M];
bool vis[M];
int h[M],cnt,dis[M];
struct Edge{int to,nxt,mn,mx;}e[M<<1];
il void add(re int u,re int v,re int mn,re int mx)
{
e[++cnt]=(Edge){v,h[u],mn,mx};h[u]=cnt;
e[++cnt]=(Edge){u,h[v],mn,mx};h[v]=cnt;
}
il ll gi()
{
re ll x=0,t=1;
re char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
return x*t;
}
il int min(re int x,re int y){return x<y?x:y;}
il int max(re int x,re int y){return x>y?x:y;}
il void Dijstra()
{
priority_queue<pi,vector<pi>,greater<pi> >Q;
while(!Q.empty()) Q.pop();
fp(i,1,n) vis[i]=0,dis[i]=1e9+7;
dis[1]=0;Q.push(mk(0,1));
while(!Q.empty())
{
re int u=Q.top().se;Q.pop();
vis[u]=1;
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to,mx=e[i].mx,mn=e[i].mn,g=max(max(lim[v],mn),dis[u]);
if(dis[v]>g&&g<=mx)
{
dis[v]=g;
Q.push(mk(dis[v],v));
}
}
while(!Q.empty()&&vis[Q.top().se]) Q.pop();
}
}
il void Pre_SPFA()
{
queue<int>Q;
while(!Q.empty()) Q.pop();
fp(i,1,n)
{
tar[i]=gi();
if(tar[i]==-1) lim[i]=1e9+7,vis[i]=1,Q.push(i);
else vis[i]=0;
}
while(!Q.empty())
{
re int u=Q.front();Q.pop();
for(re int i=h[u];i+1;i=e[i].nxt)
{
re int v=e[i].to,mn=e[i].mn,mx=e[i].mx;
if(lim[u]>mx)
if(lim[v]<mn+1)
{
lim[v]=mn+1;
if(!vis[v]) vis[v]=1,Q.push(v);
}
}
vis[u]=0;
}
}
int main()
{
freopen("lunch.in","r",stdin);
freopen("lunch.out","w",stdout);
memset(h,-1,sizeof(h));
n=gi();m=gi();
fp(i,1,m)
{
a[i].u=gi(),a[i].v=gi(),a[i].L=gi(),a[i].R=gi();
add(a[i].u,a[i].v,a[i].L,a[i].R);
}
Pre_SPFA();
Dijstra();
fp(i,1,n)
if(tar[i]==1&&dis[i]>1e9) {puts("Impossible");exit(0);}
fp(i,1,m)
{
if(tar[a[i].u]==-1)
if(dis[a[i].v]<=a[i].L) {puts("Impossible");exit(0);}
if(tar[a[i].v]==-1)
if(dis[a[i].u]<=a[i].L) {puts("Impossible");exit(0);}
}
fp(i,1,m)
{
re int u=a[i].u,v=a[i].v;
if(tar[u]==-1||tar[v]==-1) printf("%d\n",a[i].L);
else printf("%d\n",max(dis[u],dis[v])>a[i].R?a[i].L:max(a[i].L,max(dis[u],dis[v])));
}
fclose(stdin);
fclose(stdout);
return 0;
}
[noip模拟赛]午餐的更多相关文章
- NOIP模拟赛20161022
NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...
- contesthunter暑假NOIP模拟赛第一场题解
contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...
- NOIP模拟赛 by hzwer
2015年10月04日NOIP模拟赛 by hzwer (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...
- 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程
数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...
- 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...
- 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...
- 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1
题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...
- CH Round #58 - OrzCC杯noip模拟赛day2
A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...
- CH Round #52 - Thinking Bear #1 (NOIP模拟赛)
A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...
随机推荐
- [luoguP1783] 海滩防御(二分 || 最短路 || 最小生成树)
传送门 因为答案满足单调性,所以看到这个题,第一反应是二分,但是总是WA,也没有超时. 看了题解,,,,,, 这题刚开始很多人会想到二分,二分答案,然后看看是否能绕过所有信号塔,但是,这样写明显超时, ...
- SQL Server 创建唯一约束sql语句
SQL Server 创建唯一约束sql语句 语句示例: 在创建表是时同时创建, 创建id,name,sex三个字段的唯一索引 create table t1( id int primary ...
- 为什么zookeeper的节点配置的个数必须是奇数个?
zookeeper有这样一个特性:集群中只要有过半的机器是正常工作的,那么整个集群对外就是可用的.也就是说如果有2个zookeeper,那么只要有1个死了zookeeper就不能用了,因为1没有过半, ...
- 多线程调用COM组件的体会(CoInitialize)
调用任何COM组件之前,你必须首先初始化COM套件环境,即调用CoInitialize或CoInitializeEx.COM套件环境在线程的生存周期内有效,线程退出前需要调用CoUninitializ ...
- grails的criteria和hql查询
grails在查询方面也保留了hibernate的hql和criteria查询功能.hql自然不必多说基本不会有什么变化,grails的criteria查询在hibernate上面做了微调使用起来更加 ...
- Angular结构简单介绍
在当前项目目录下,使用Angular-CLI生成一个组件:heroes ng generate component heroes 主界面(也就是一个主模块+多个单模块,例如我们创建的heroes(单模 ...
- coco2d-js demo程序之滚动的小球
近期有一个游戏叫围住神经猫,报道说是使用html5技术来做的. html5的跨平台的优良特性非常不错.对于人手不足,技术不足,选用html5技术实现跨平台的梦想真是不错. 近期在看coco2d-js这 ...
- HDU 5303 Delicious Apples (贪心 枚举 好题)
Delicious Apples Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Other ...
- vue Iframe
1.Iframe.vue <!-- Iframe --> <template> <div> <!-- 标题栏 --> <mt-header tit ...
- FZU 2150 Fire Game (暴力BFS)
[题目链接]click here~~ [题目大意]: 两个熊孩子要把一个正方形上的草都给烧掉,他俩同一时候放火烧.烧第一块的时候是不花时间的.每一块着火的都能够在下一秒烧向上下左右四块#代表草地,.代 ...