当前位置: 首页 > news >正文

解题报告-P11844 [USACO25FEB] Friendship Editing G

P11844 [USACO25FEB] Friendship Editing G

题目描述

Farmer John 的 \(N\) 头奶牛编号为 \(1\)\(N\)\(2\le N\le 16\))。奶牛之间的朋友关系可以建模为一个有 \(M\)\(0\le M\le N(N-1)/2\))条边的无向图。两头奶牛为朋友当且仅当图中她们之间存在一条边。

在一次操作中,你可以添加或删除图中的一条边。计算确保以下性质成立所需的最小操作次数:如果奶牛 \(a\)\(b\) 是朋友,则对于每头其他奶牛 \(c\)\(a\)\(b\) 中至少之一与 \(c\) 是朋友。

输入格式

输入的第一行包含 \(N\)\(M\)

以下 \(M\) 行,每行包含一对朋友 \(a\)\(b\)\(1\le a<b\le N\))。每对朋友出现至多一次。

输出格式

输出你需要增加或删除的边的数量。

输入输出样例 #1

输入 #1

3 1
1 2

输出 #1

1

输入输出样例 #2

输入 #2

3 2
1 2
2 3

输出 #2

0

输入输出样例 #3

输入 #3

4 4
1 2
1 3
1 4
2 3

输出 #3

1

说明/提示

样例 1 解释:

该网络不符合性质。我们可以添加边 \((2,3)\)\((1,3)\),或删除边 \((1,2)\) 进行修复。

样例 2 解释:

不需要进行任何修改。

  • 测试点 \(4\sim 13\):对于每一个 \(N\in [6, 15]\) 依次有一个测试点。
  • 测试点 \(14\sim 18\)\(N=16\)

解题报告

我艹,牛逼!!!

先给出一个很难发现的性质:每一个符合条件的关系图,这个图的补图是由若干不相交团组成(团是完全图)

下面是一个经典的证明:

如果奶牛 ab 是朋友,则对于每头其他奶牛 cab 中至少之一与 c 是朋友,假设 a,b 不是朋友,就会有两种情况。(cab 外任意一点)

1.  a   b   2.  a   b\ /c           c

考虑建补图:

1.  a---b   2.  a---b\ /c           c

将图扩展可以推出,ab 外任意一个点要么和 ab 都有连接,要么和 ab 都没连接。同理,两个点与同一个点都有连接,那这两个点也有连接。

所以只要有 ab 外的两点 cd 都跟 ab 有连接,cd 之间就也会有连接,这时 abcd 就会形成一个团,所以整个图就是很多团的并集。

所以问题就转换成了求将一个图的补图修改成很多团的并集的最小操作次数

根据数据范围的提示,我们可以尝试状压 DP。

设点集 \(i\) 表示被选择的点,状态数组为 \(dp[i]\) 表示将这些点改成若干团的并的最小操作次数。

显然有以下转移:

\[dp[i]=\min_{j \in i} (dp[j]+cost(j \oplus i)) \]

\(cost(j \oplus i)\)表示的是将点集 \(j \oplus i\) 代表的图改成团的最小代价。这个方程表示从点集 \(i\) 中的一些点改成完全图的最小代价加上剩余点改成若干个团的最小代价。

每个点集 \(i\)\(cost(i)\) 都可以被预处理出来,统计每两个属于点集 \(i\) 的点之间不存在边的个数(连边),再加上每个属于点集 \(i\) 的点和每个不属于点集 \(i\) 的点之间存在的边的个数(删边),就完成了。

预处理部分时间复杂度 \(O(n^2 \times 2^n)\),状压 DP 部分时间复杂度 \(O(3^n)\),代码如下:

#include<bits/stdc++.h>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=21;#define ckmax(x,y) ( x=max(x,y) )
#define ckmin(x,y) ( x=min(x,y) )inline int read()
{int f=1,x=0; char ch=getchar();while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }while(isdigit(ch))  { x=x*10+ch-'0';    ch=getchar(); }return f*x;
}bool e[N][N];
int n,m;
int g[1<<N];
int dp[1<<N];signed main()
{n=read(),m=read();for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)e[i][j]=1;for(int i=1;i<=m;i++){int u=read(),v=read();e[u][v]=e[v][u]=false;}for(int k=0;k<(1<<n);k++)for(int i=1;i<=n;i++){if( !( k&(1<<i-1) ) ) continue;for(int j=1;j<=n;j++){if(i==j) continue;g[k]+=( k&(1<<j-1) ? (!e[i][j]):e[i][j] );}}for(int i=0;i<(1<<n);i++){dp[i]=g[i];for(int j=i;j;j=(j-1)&i)ckmin(dp[i],dp[i^j]+g[j]);}printf("%d",dp[(1<<n)-1]/2);return 0;
}
http://www.wxhsa.cn/company.asp?id=6975

相关文章:

  • 两种判断计算机大小端模式的方法
  • CSP-S模拟23
  • CF1413F Roads and Ramen
  • 复现The Annotated Transformer代码时遇到的问题和相关链接
  • Node.js 文件上传中文文件名乱码难题,为什么只有Node会有乱码困难,其他后端框架少见?
  • ROS2之节点
  • 9.17日总结
  • ECT-OS-JiuHuaShan 框架,元推理AGI奇迹
  • Mapper与Mapper.xml的关系
  • Rocky Linux10.0安装zabbix7.4详细步骤 - 教程
  • 【P3158】放棋子 - Harvey
  • 最强AI语音克隆和文本配音工具!与真人无异,CosyVoice下载介绍
  • 近日C++线上练习结果
  • 密力根油滴实验实验报告
  • Linux 系统插入U盘/移动硬盘实现自动挂载
  • 来点人瑞平我
  • 【P2051】中国象棋 - Harvey
  • JavaDay6
  • Ubuntu Linux 云服务器常见安全漏洞修复方法汇总 Apache/OpenSSH/DNS
  • AI智能体开发实战:从提示工程转向上下文工程的完整指南
  • 解码C语言九条语句
  • 多个 root 用户记录,而且有些记录的密码是空的,导致认证混乱。
  • 解题报告-P11670 [USACO25JAN] Cow Checkups S
  • word vba 对 带编号格式的PO单 段落下添加对应的图片
  • 解题报告-P11671 [USACO25JAN] Farmer Johns Favorite Operation S
  • 解码C语言运算符
  • 多进程
  • 93. 递归实现组合型枚举
  • Sort方法学习(伪代码记录)
  • 深入解析:【每日一问】运算放大器与比较器有什么区别?