CF 1027F Session in BSU (并查集+树上构造)

题目大意:你可以在第$ai$天或者第$bi$天进行第$i$场考试,每天最多进行一场考试,求把所有考试都考完的最早结束时间

由于天数可能很大,需要离散

把问题抽象成一棵树,每个点最多被"分配"一条边,现在要删点

画画图可以发现

如果一个联通块是一棵树,那么可以删去至多一个点

如果一个联通块是一个单环树(n个点n条边),那么一个点都不能删掉

如果一个联通块边数大于点数,会发现无法把每个点只分配一条边,不合法,输出-1

判树还是单环树,求一个联通块内点的度总和/2和点数比较即可

并查集维护一下点属于哪个联通块即可

注意点数是$2*10^6$而不是$1*10^6$

 1 #include <queue>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #define N 2000100
 6 #define maxn 100000
 7 #define ll long long
 8 #define mod 1000000007
 9 #define iset multiset<node>::iterator
10 using namespace std;
11 //re
12 int gint()
13 {
14     int ret=0,fh=1;char c=getchar();
15     while(c<‘0‘||c>‘9‘){if(c==‘-‘)fh=-1;c=getchar();}
16     while(c>=‘0‘&c<=‘9‘){ret=ret*10+c-‘0‘;c=getchar();}
17     return ret*fh;
18 }
19 int n,m,K,ma,cte,num;
20 int head[N],inc[N],id[N*2],vis[N],fa[N],sum[N],sz[N],typ[N];
21 struct E{int x,y;}e[N];
22 struct Edge{int to,nxt,val;}edge[N*2];
23 void ae(int u,int v){
24     cte++;edge[cte].to=v,inc[v]++;
25     edge[cte].nxt=head[u],head[u]=cte;}
26 int find_fa(int x){
27     int y=x,pre;while(fa[y]!=y){y=fa[y];}
28     while(fa[x]!=y){pre=fa[x],fa[x]=y,x=pre;}
29     return y;
30 }
31 int dfs(int u)
32 {
33     vis[u]=1;int ans=1;
34     for(int j=head[u];j;j=edge[j].nxt){
35         int v=edge[j].to;
36         if(vis[v]) continue;
37         fa[v]=u,ans+=dfs(v),sz[u]+=sz[v];
38     }sz[u]+=inc[u];return ans;
39 }
40
41 int main()
42 {
43     scanf("%d",&n);
44     int x,y,z,fx;
45     for(int i=1;i<=n;i++)
46         e[i].x=gint(),e[i].y=gint(),
47         id[++num]=e[i].x,id[++num]=e[i].y;
48     sort(id+1,id+num+1);
49     num=unique(id+1,id+num+1)-(id+1);
50     for(int i=1;i<=n;i++){
51         x=lower_bound(id+1,id+num+1,e[i].x)-id;
52         y=lower_bound(id+1,id+num+1,e[i].y)-id;
53         ae(x,y),ae(y,x);
54     }int tot;
55     for(int i=1;i<=num;i++) fa[i]=i;
56     for(int i=1;i<=num;i++)
57         if(!vis[i]){
58             sum[i]=dfs(i);
59             if(sum[i]==(sz[i]+2)/2)
60                 typ[i]=1;
61             else if(sum[i]==(sz[i]/2))
62                 typ[i]=0;
63             else{printf("-1\n");return 0;}
64         }
65     int ans=num;
66     for(int i=num;i>=1;i--){
67         fx=find_fa(i);
68         if(typ[fx]==1) {typ[fx]=0;ans=i-1;}
69         else break;
70     }
71     printf("%d\n",id[ans]);
72     return 0;
73 }

原文地址:https://www.cnblogs.com/guapisolo/p/9841106.html

时间: 2024-08-29 14:46:01

CF 1027F Session in BSU (并查集+树上构造)的相关文章

CF.1027F.Session in BSU(思路 并查集)

题目链接 \(Description\) 有\(n\)个人都要参加考试,每个人可以在\(ai\)或\(bi\)天考试,同一天不能有两个人考试.求最晚考试的人的时间最早能是多少.无解输出-1. \(Solution\) 把每个人向\(ai,bi\)连边.对于每个连通块单独考虑. 记点数为n,边数为m.可以发现当某一连通块n>m(n=m+1)时,可以有一个点不选(最大的): 当n=m时,所有点都要选:n<m时,无解. 用并查集维护连通,顺便维护最大.次大值.当第一次出现环时,即n=m:第二次出现就

[Codeforces 1027 F] Session in BSU [并查集维护二分图匹配问题]

题面 传送门 思路 真是一道神奇的题目呢 题目本身可以转化为二分图匹配问题,要求右半部分选择的点的最大编号最小的一组完美匹配 注意到这里左边半部分有一个性质:每个点恰好连出两条边到右半部分 那么我们可以利用这个性质 考虑一个左边的点和它右边联通的两个点,发现这两个点只能选择一个和这个左边的点匹配 那么我们考虑把这个点点匹配的模型转化成点边匹配 我们在同一个左边点连的两个右边点之间连边,那么问题就变成了一个点和一条相邻的边匹配,求完美匹配的问题了 而这个问题,我们显然可以用并查集来很好的解决 考虑

(POJ1182)食物链(带权并查集-附通用模板)

食物链 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 74914   Accepted: 22257 Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同

并查集学习

从HOJ1232来学习并查集 #include<iostream> #include<vector> using namespace std; //封装好的并查集 class UF{//union find private: vector<int> v;//存储各个结点 v[i]=j 表示 第i个结点的代表元是j(所在树的根结点) public: //初始化 UF(int n){//初始化 总共有n个结点 刚开始的时候v[i]=i for(int i=0;i<=n

[POJ 2588]--Snakes(并查集)

题目链接:http://poj.org/problem?id=2588 Snakes Time Limit: 1000MS   Memory Limit: 65536K   Description Buffalo Bill wishes to cross a 1000x1000 square field. A number of snakes are on the field at various positions, and each snake can strike a particular

B. Mr. Kitayuta&#39;s Colorful Graph (CF #286 (Div. 2) 并查集)

B. Mr. Kitayuta's Colorful Graph time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Mr. Kitayuta has just bought an undirected graph consisting of n vertices and m edges. The vertices of the g

CF 115 A 【求树最大深度/DFS/并查集】

CF A. Party time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard output A company has n employees numbered from 1 to n. Each employee either has no immediate manager or exactly one immediate manager, who

CF 500 B. New Year Permutation 并查集

User ainta has a permutation p1, p2, ..., pn. As the New Year is coming, he wants to make his permutation as pretty as possible. Permutation a1, a2, ..., an is prettier than permutation b1, b2, ..., bn, if and only if there exists an integer k (1 ≤ k

[CF#250 Div.2 D]The Child and Zoo(并查集)

题目:http://codeforces.com/problemset/problem/437/D 题意:有n个点,m条边的无向图,保证所有点都能互通,n,m<=10^5 每个点都有权值,每条边的权值定义为这条边连接两点的权值中的最小值. f(p,q)表示p到q的路径中边权的最小值,如果有多条路经,就取每条路径最小值中的最小值 要求的就是对于所有1<=p<=n,1<=q<=n,p≠q,f(p,q)的平均值 分析: 刚开始是想考虑每条边对总和的贡献,结果没想通. 一个很巧的办法