题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4883 首先,注意到每个点可横可竖,但花费一样: 所以考虑行列的交集,那么这个条件可以转化为行点和列点之间的边,边权就是花费: 如果行和列都按原图交点连了边,那么问题就转化成在有向图中,每个点(原图的行/列)都有且仅有1入度: 这个性质让我们联想到基环树,所以只需要构造一个基环树森林即可: 又要边权和最小,仿照 Kruskal,从小到大加边,对于连通块,看看是否已经有环即可. 代码如下: #…
BZOJ4883 棋盘上的守卫 考虑费用流,但是数据范围太大 考虑 \(i\) 行 \(j\) 列如果被选择,那么要么给 \(i\) 行,要么给 \(j\) 列 把选择 \(i\) 行 \(j\) 列当做一条边,每一行每一列建成一个点,于是我们可以用边的方向来代表我们给的究竟是第 \(i\) 行还是第 \(j\) 列 这样,当全部覆盖以后,我们发现图的每个点入度为 \(1\) ,本质上是一个基环森林,于是我们不需要考虑边的方向,只需要求出基环森林即可. 可以魔改 kruskal ,判断当前联通块…
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4883 题意:给出一个$N \times M$的棋盘,每个格子有权值.你需要每一行选中一个格子,每一列也选中一个格子(一个格子不能同时被行选中和被列选中),求这些格子权值和的最小值,$2 \leq N,M \leq 10^5 , N \times M \leq 10^5$ 考虑将行与列拆成点,格子的权值变为连接其对应行与列对应节点的边,我们的问题也就是需要找到一个边集,使得每一条边都在…
http://www.lydsy.com/JudgeOnline/problem.php?id=1040 题意: 思路: 这是基环树,因为每个人只会有一个厌恶的人,所以每个节点只会有一个父亲节点,但是根节点也是有父亲节点的,所以在树中肯定是存在一个环的,只要删除该环中的任意一条边,那么就能将该图变成一颗树. 如果是树的话,那就很简单了,d[u][0/1] dp求解即可. 现在假设删除的边是e,两端的节点分别是u,v,首先对u为根的树作一次dp,最后取d[u][0](v取不取都无所谓),不能取d[…
传送门 题解 题意 = 找出无向基环树森林的每颗基环树的直径. 我们首先需要找到每颗基环树的环, 但是因为是无向图,用tarjan找环, 加个手工栈, 我也是看了dalao的博客才知道tarjan找无向图环 : dalao的链接 然鹅大佬的方法有一点小问题, 无法找出只有两个节点的环,改动后代码: void dfs(int x, int last) { dfn[x] = ++sz; for(int i = head[x]; i; i = e[i].nxt) { ) continue; int n…
没考虑可以连着两个不选--直接染色了 实际上是基环森林,对于每棵基环树,dfs找出一个环边,然后断掉这条边,分别对这条边的两端点做一边treedp,取max加进答案里 treedp是设f[u]为选u点,g[u]为不选u点,然后随便转移一下就行了 #include<iostream> #include<cstdio> using namespace std; const int N=1000005; int n,h[N],cnt=1,x,y,eg; long long a[N],f[…
题意:给定N点N边的无向连通图,现在让你在图中找一点作为餐厅,使得最远点距离这点最近. 思路:为了保留整数,我们求最小直径,最后去除2.  直径来源于两部分: 1,在外向树中: 那么就是树的直接,一棵树求直径直接跑一边DP就可以了.(或者两遍BFS吧,麻烦一点而已),假设最大值为ans1. 2,可能通过了环. 一定有环上的边不在直接上,我们枚举这个断边. 那么现在就相当于一个X元环,环上的边有权值,X个点也各有权值,现在枚举每个断边,变成一条带枝桠的链,让你求ans2=min(最长链). 答案就…
Description 在一个n*m的棋盘上要放置若干个守卫.对于n行来说,每行必须恰好放置一个横向守卫:同理对于m列来说,每列 必须恰好放置一个纵向守卫.每个位置放置守卫的代价是不一样的,且每个位置最多只能放置一个守卫,一个守卫 不能同时兼顾行列的防御.请计算控制整个棋盘的最小代价. Input 第一行包含两个正整数n,m(2<=n,m<=100000,n*m<=100000),分别表示棋盘的行数与列数. 接下来n行,每行m个正整数 其中第i行第j列的数w[i][j](1<=w[…
传送门 BZOJ Solution 考虑一下如果把行,列当成点,那么显然这个东西就是一个基环树对吧. 直接按照\(Kruscal\)那样子搞就好了. 代码实现 代码戳这里…
题意 有一大小为 \(n*m\) 的棋盘,要在一些位置放置一些守卫,每个守卫只能保护当前行列之一,同时在每个格子放置守卫有一个代价 \(w\) ,问要使得所有格子都能够被保护,需要最少多少的代价. \(2\leq n,m\leq 10^5\ ,n*m\leq 10^5\) 分析 将行列看成 \(n+m\) 个点.将每个格点放置守卫看成所在行列连了一条边,然后把每条边定向,如果被指向表示当前格点对当前 行/列 进行了保护. 这样就会有 \(n+m\) 个点,\(n+m\) 条有向边,同时每条边最多…