CF1027F Session in BSU

link

 

花絮:

这场看起来打得还不错的样子……(别问我是用哪个号打的)。

然后听说这题的思想被出了好多次,女生赛也出过,quailty算法,然而当时没反应过来,而且时间不多啦。

 

题意:

有n个人,每个人有两个时间点可以参加考试,任意两人不能在同一时间点参加考试。问最迟考试的人的考试时间最早是多少?

$n\leq 10^6.$

 

题解:

离散化,将每人的两个时间点连边。题意可以转化为:给每条边定向满足任意一点入度至多为1,使得每条边指向的点的编号最大值最小。

要满足任意一点入度至多为1,原图必须是基环森林(每个连通块必须是基环树或树)。先判不合法的情况。然后对于每个连通块,如果是基环树,那么每个点一定有1的入度,用最大值更新答案;如果是树,那么最多使得根节点没有入度,其余点都有1的入度,所以把最大编号设为根,用次大值更新答案。每个连通块的值的最大值即为最终答案。

复杂度$\mathcal{O}(n\log n)$。

代码实现可能不是很简洁明了(好像可以用并查集维护),不过思路是没错的。

 

code:

 1 #include<bits/stdc++.h>
 2 #define rep(i,x,y) for (int i=(x);i<=(y);i++)
 3 #define ll long long
 4 #define inf 1000000001
 5 #define y1 y1___
 6 #define pii pair<int,int>
 7 #define fi first
 8 #define se second
 9 using namespace std;
10 char gc(){
11     static char buf[100000],*p1=buf,*p2=buf;
12     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
13 }
14 #define gc getchar
15 ll read(){
16     char ch=gc();ll x=0;int op=1;
17     for (;!isdigit(ch);ch=gc()) if (ch=='-') op=-1;
18     for (;isdigit(ch);ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
19     return x*op;
20 }
21 #define N 2000005
22 int n,sl,q[N],cnt=1,head[N],num,Mx,Mx2,vis[N],dep[N],ans;
23 struct edge{int to,nxt;}e[N];
24 struct node{int x,y;}a[N];
25 void adde(int x,int y){e[++cnt].to=y;e[cnt].nxt=head[x];head[x]=cnt;}
26 void dfs(int u,int pr){
27     vis[u]=1;
28     if (q[u]>Mx) Mx2=Mx,Mx=q[u];else Mx2=max(Mx2,q[u]);
29     for (int i=head[u];i;i=e[i].nxt) if ((i^1)!=pr){
30         int v=e[i].to;
31         if (!vis[v]) dep[v]=dep[u]+1,dfs(v,i);
32         else if (dep[u]>dep[v]) num++;
33     }
34 }
35 int main(){
36     n=read();int x,y;
37     rep (i,1,n){
38         q[++sl]=a[i].x=read(),q[++sl]=a[i].y=read();
39         if (a[i].x>a[i].y) swap(a[i].x,a[i].y);
40     }
41     sort(&q[1],&q[sl+1]);sl=unique(&q[1],&q[sl+1])-q-1;
42     rep (i,1,n){
43         a[i].x=lower_bound(&q[1],&q[sl+1],a[i].x)-q;
44         a[i].y=lower_bound(&q[1],&q[sl+1],a[i].y)-q;
45         adde(a[i].x,a[i].y);adde(a[i].y,a[i].x);
46     }
47     rep (i,1,sl) if (!vis[i]){
48         num=Mx=Mx2=0;
49         dfs(i,0);
50         if (num>1) return puts("-1"),0;
51         if (num==1) ans=max(ans,Mx);else ans=max(ans,Mx2);
52     }
53     printf("%d\n",ans);
54     return 0;
55 }
View Code

 

posted @ 2018-08-19 10:58  bestfy  阅读(209)  评论(0编辑  收藏  举报