[cf587D]Duff in Mafia
二分最大边权,即有些边强制不能被选
接下来,即任意一点上某两边不能同时被选,以及任意一点上颜色相同的两边必须被选择一条
这些限制都可以用2-sat的形式来描述(强制不能选即连边"选->不选"),但后两类的边数达到了$o(m^{2})$,时间复杂度上无法接受
当一个节点上有一种颜色的边出现3次,或有两种颜色的边出现两次,必然不合法,因此第3类限制的边每一个点上至多只有1条,即为$o(n)$
对于第2类限制,即该点上任意一边都要向其余边连线,那么即新建一些点来优化连边
更具体的,假设某个点上相关的边分别对应点$a_{1},a_{2},...,a_{k}$和$a'_{1},a'_{2},...,a_{k}$(后者表示不选),即需要连边$(a_{i},a'_{j})$(其中$i\ne j$)
新建$s_{1},s_{2},...,s_{k}$,连边$(s_{i},s_{i-1})$和$(s_{i},a'_{i})$,再连边$(a_{i},s_{i-1})$即实现了连边$(a_{i},a'_{j})$(其中$j<i$)
对于$j>i$类似,即连边$(s'_{i},s'_{i+1})$和$(s'_{i},a'_{i})$,再连边$(a_{i},s'_{i+1})$即可
综上,即将边数优化为$o(m)$,可以通过
(关于这个,也可以理解为前后缀的构造)

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 struct Edge{
5 int nex,to,color,len;
6 }edge[N];
7 vector<int>v,ans,A[N*3],B[N*3];
8 map<int,int>tot,lst;
9 int V,E,n,m,x,y,c,z,scc,head[N],vis[N*3],dfn[N*3],bl[N*3];
10 void add_edge(int x,int y,int c,int z){
11 edge[E].nex=head[x];
12 edge[E].to=y;
13 edge[E].color=c;
14 edge[E].len=z;
15 head[x]=E++;
16 }
17 void add_2sat(int x,int y){
18 A[x].push_back(y);
19 B[y].push_back(x);
20 }
21 void del_2sat(int x,int y){
22 A[x].pop_back();
23 B[y].pop_back();
24 }
25 void dfs1(int k){
26 if (vis[k])return;
27 vis[k]=1;
28 for(int i=0;i<A[k].size();i++)dfs1(A[k][i]);
29 dfn[++dfn[0]]=k;
30 }
31 void dfs2(int k){
32 if (bl[k])return;
33 bl[k]=scc;
34 for(int i=0;i<B[k].size();i++)dfs2(B[k][i]);
35 }
36 bool calc(int k){
37 for(int i=0;i<E;i+=2)
38 if (edge[i].len>k)add_2sat((i>>1),(i>>1)+m);
39 scc=dfn[0]=0;
40 memset(vis,0,sizeof(vis));
41 memset(bl,0,sizeof(bl));
42 for(int i=0;i<V;i++)
43 if (!vis[i])dfs1(i);
44 for(int i=dfn[0];i;i--)
45 if (!bl[dfn[i]]){
46 scc++;
47 dfs2(dfn[i]);
48 }
49 bool flag=1;
50 for(int i=0;i<m;i++)
51 if (bl[i]==bl[i+m]){
52 flag=0;
53 break;
54 }
55 for(int i=0;i<E;i+=2)
56 if (edge[i].len>k)del_2sat((i>>1),(i>>1)+m);
57 return flag;
58 }
59 int main(){
60 scanf("%d%d",&n,&m);
61 memset(head,-1,sizeof(head));
62 for(int i=1;i<=m;i++){
63 scanf("%d%d%d%d",&x,&y,&c,&z);
64 add_edge(x,y,c,z);
65 add_edge(y,x,c,z);
66 }
67 V=(m<<1);
68 for(int i=1;i<=n;i++){
69 x=y=-1;
70 v.clear(),tot.clear(),lst.clear();
71 for(int j=head[i];j!=-1;j=edge[j].nex){
72 tot[edge[j].color]++;
73 if (tot[edge[j].color]>2){
74 printf("No");
75 return 0;
76 }
77 if (tot[edge[j].color]==2){
78 if ((x>=0)&&(y>=0)){
79 printf("No");
80 return 0;
81 }
82 x=(lst[edge[j].color]>>1);
83 y=(j>>1);
84 }
85 lst[edge[j].color]=j;
86 v.push_back(j>>1);
87 }
88 if ((x>=0)&&(y>=0)){
89 add_2sat(x+m,y);
90 add_2sat(y+m,x);
91 }
92 for(int j=0;j<v.size();j++){
93 add_2sat(V+j,v[j]+m);
94 add_2sat(V+j+v.size(),v[j]+m);
95 }
96 for(int j=1;j<v.size();j++){
97 add_2sat(V+j,V+j-1);
98 add_2sat(V+j+v.size()-1,V+j+v.size());
99 add_2sat(v[j],V+j-1);
100 add_2sat(v[j-1],V+j+v.size());
101 }
102 V+=(v.size()<<1);
103 }
104 int l=0,r=0x3f3f3f3f;
105 while (l<r){
106 int mid=(l+r>>1);
107 if (calc(mid))r=mid;
108 else l=mid+1;
109 }
110 if (l==0x3f3f3f3f)printf("No");
111 else{
112 calc(l);
113 for(int i=0;i<m;i++)
114 if (bl[i]>bl[i+m])ans.push_back(i+1);
115 printf("Yes\n%d %d\n",l,ans.size());
116 for(int i=0;i<ans.size();i++)printf("%d ",ans[i]);
117 }
118 }
[cf587D]Duff in Mafia的更多相关文章
- 【CF587D】Duff in Mafia 二分+前缀优化建图+2-SAT
[CF587D]Duff in Mafia 题意:给你一张n个点m条边的无向图,边有颜色和边权.你要从中删去一些边,满足: 1.任意两条删掉的边没有公共的顶点.2.任意两条剩余的.颜色相同的边没有公共 ...
- Codeforces 587D - Duff in Mafia(2-SAT+前后缀优化建图)
Codeforces 题面传送门 & 洛谷题面传送门 2-SAT hot tea. 首先一眼二分答案,我们二分答案 \(mid\),那么问题转化为,是否存在一个所有边权都 \(\le mid\ ...
- 2021record
2021-10-14 P2577 [ZJOI2004]午餐 2021-10-13 CF815C Karen and Supermarket(小小紫题,可笑可笑) P6748 『MdOI R3』Fall ...
- 2-SET 前缀优化建图
1, Duff in Mafia CodeForces - 587D 2, Ants CodeForces - 1007D
- cf Round 587
A.Duff and Weight Lifting(思维) 显然题目中只有一种情况可以合并 2^a+2^a=2^(a+1).我们把给出的mi排序一下,模拟合并操作即可. # include <c ...
- Codeforces Round #326 (Div. 2) B. Pasha and Phone C. Duff and Weight Lifting
B. Pasha and PhonePasha has recently bought a new phone jPager and started adding his friends' phone ...
- 【转】Duff's Device
在看strcpy.memcpy等的实现发现用了内存对齐,每一个word拷贝一次的办法大大提高了实现效率,参加该blog(http://totoxian.iteye.com/blog/1220273). ...
- [BZOJ1163][BZOJ1339][Baltic2008]Mafia
[BZOJ1163][BZOJ1339][Baltic2008]Mafia 试题描述 匪徒准备从一个车站转移毒品到另一个车站,警方准备进行布控. 对于每个车站进行布控都需要一定的代价,现在警方希望使用 ...
- Codeoforces 558 B. Duff in Love
// B. Duff in Love time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
随机推荐
- AT3950 [AGC022E] Median Replace
题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,里面有一些还没有确定,我们标记为 ? .可以进行若干次操作,每次操作可以把三个相邻的数替换成它们的中位数.问有多少种 ...
- 模拟赛T2 交换 解题报告
模拟赛T2 交换 解题报告 题目大意: 给定一个序列和若干个区间,每次从区间中选择两个数修改使字典序最小. \(n,m\) 同阶 \(10^6\) 2.1 算法 1 按照题意模拟,枚举交换位置并比较. ...
- Oracle job的用法
1.Broken()过程更新一个已提交的工作的状态,典型地是用来把一个已破工作标记为未破工作. 这个过程有三个参数:job .broken与next_date. PROCEDURE Broken (j ...
- NX9.0和NX10.0做自定义操作可以用的函数
NX9.0:LIBUFUNX.DLL int UF_OPER_ask_check_geom(void *,int *,unsigned int * *) int UF_OPER_ask_first_o ...
- python中常用的导包的方法和常用的库
python中常用的导包的方法 导入包和包名的方法:1.import package.module 2.from package.module import * 例一: ...
- Go语言核心36讲(Go语言进阶技术四)--学习笔记
10 | 通道的基本操作 作为 Go 语言最有特色的数据类型,通道(channel)完全可以与 goroutine(也可称为 go 程)并驾齐驱,共同代表 Go 语言独有的并发编程模式和编程哲学. D ...
- Python 做简单的登录系统
案例 之 登录系统原创作品1 该随笔 仅插入部分代码:全部py文件源代码请从百度网盘自行下载! 链接:https://pan.baidu.com/s/1_sTcDvs5XEGDcnpoQEIrMg 提 ...
- .net 5.0 ref文件夹的作用
ref目录里的dll是一个名为参考组件的东西,微软MSDN给的解释是 参考组件是一种特殊类型的程序集,仅包含表示库的公共API面所需的最小元数据数量.它们包括用于在构建工具中引用程序集时重要的所有成员 ...
- Scrum Meeting 0531
零.说明 日期:2021-5-31 任务:简要汇报两日内已完成任务,计划后两日完成任务 一.进度情况 组员 负责 两日内已完成的任务 后两日计划完成的任务 困难 qsy PM&前端 完成后端管 ...
- BUAA 2020 软件工程 热身作业
BUAA 2020 软件工程 热身作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! ...