详见2018集训队论文《浅谈拟阵的一些拓展及其应用》
我仅仅是读了粗略的读了论文(跳过了若干证明),感性的理解了拟阵和拟阵交
然后写了两道模板题。
可能有很多疏漏的地方,请各位大佬指正。
拟阵的定义 wiki
这里只有摘要
M = ( S , I ) , I M = (S,I) , I M=(S,I),I是独立集的集合
满足遗传性:I的一切子集也是独立集
交换性:A,B是独立集, ∣ A ∣ < ∣ B ∣ |A| < |B| ∣A∣<∣B∣ , 则存在 B\A 中元素x, A + x A + {x} A+x也是独立集一般常用的还有 对偶拟阵 M ∗ = ( S , I ∗ ) , I ∗ = X : S X 中 包 含 M 的 基 M* = (S,I*) , I* = {X : S \ X 中包含M的基} M∗=(S,I∗),I∗=X:S X中包含M的基
拟阵的秩函数 M = ( S , R ) , R = I : r ( I ) = ∣ I ∣ M = (S,R) , R = {I : r(I) = |I|} M=(S,R),R=I:r(I)=∣I∣ 关于秩函数对拟阵的定义和独立集的遗传性、交换性定义是等价的
拟阵交
顾名思义,给出两个拟阵,求交的最大(权)独立集
注意,多个拟阵的交可以规约到哈密顿路径,是NP问题
算法流程(此处截取自原论文)
例1 NAIPC 2018 G - Rainbow Graph
注意图联通不是拟阵,而考虑删边,可以得到图拟阵的对偶拟阵
好像网上很多代码都写的是把权值取负,跑最短路
而我直接按照对偶阵的定义写的,权值仍然是论文中提到的被选取为负,未选取为正,故跑最长路
这里要说明一下。按照我的理解,论文中说的求最大权独立集应该求最长路(每次增广权值最大的路径,且仍然满足最大独立集的性质)。可能是我对作者的意思理解有误。但是两道题中我按照自己的思路写,的确得出了正确的答案
#include<bits/stdc++.h>
using namespace std;
#define PB push_back
#define lowbit(x) (x&(-x))
#define MP make_pair
#define fi first
#define se second
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define rep(i,l,r) for (int i = l ; i <= r ; i++)
#define down(i,r,l) for (int i = r ; i >= l ; i--)
#define fore(i,x) for (int i = head[x] ; i ; i = e[i].next)
#define SZ(v) (int)v.size()
typedef long long ll;
typedef pair <int,int> pr;
const int maxn = 1e6 + 10;
const int inf = 1e9;
int n,m;
int weight[maxn];
struct graph{
vector <vector<pr>> e;
graph(){
}
graph(int n){
e.assign(n,vector <pr> (0)); }
void adde(int x,int y,int id){
e[x].PB({
y,id});
e[y].PB({
x,id});
}
bool check(const vector <int> &used){
vector <int<