[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 ...
随机推荐
- 我是一个线程 - IBM刘欣
来自:码农翻身(微信号:coderising) 作者:IBM刘欣 我是一个线程,我一出生就被编了个号: 0×3704,然后被领到一个昏暗的屋子里, 这里我发现了很多和我一模一样的同伴. 我身边的同伴0 ...
- JS中的call()和apply()方法区别
如 果没接触过动态语言,以编译型语言的思维方式去理解javaScript将会有种神奇而怪异的感觉,因为意识上往往不可能的事偏偏就发生了,甚至觉得不可 理喻.如果在学JavaScript这自由而变幻无穷 ...
- msp430项目编程32
msp430中项目---电阻测量系统32 Ad 1.电路工作原理 2.代码(显示部分) 3.代码(功能实现) 4.项目总结
- equals() 和 hashCode()
equals() 和 hashCode()这两个方法在java.lang.Object中,所有的类都可以继承这两个方法: 但是,这两个方法在Object类中的实现一般没什么用,所以你通常需要自己重载这 ...
- 从零开始写STL-二叉搜索树
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的 ...
- 洛谷——P1262 间谍网络
P1262 间谍网络 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意 ...
- 3469 [POI2008]BLO-Blockade
洛谷—— P3469 [POI2008]BLO-Blockade 题目描述 There are exactly towns in Byteotia. Some towns are connected ...
- Palindrome Partitioning (回文子串题)
Given a string s, partition s such that every substring of the partition is a palindrome. Return all ...
- python菜鸟日记1
1. 在__init__(self,...)初始化函数中.定义对象的属性,这些属性不用所有写在括号里,括号里的表示定义的时候须要赋初始值的一些属性,而其它不用初始值的属性.能够 直接卸载代码块中,se ...
- POST & GET & Ajax 全解
GET&POST&Ajax 全解 一.POST和GET的差别 GET:GET方法提交数据不安全,数据置于请求行.客户段地址栏可见:GET方法提交的数据限制大小在255个字符之内.參数直 ...