带权拟阵交
带权拟阵交板题 2023HDU多校3 1006
注意带权拟阵交是指在最大交的前提下的最大权值的交。
#include<cstdio>
#include<vector>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int N=65;
int Case,n,i,j,x,y,g[N],v[N<<1],nxt[N<<1],ed,ans;
ull num[N][2];
int val[N][2],f[N][2][2];
struct Item {
ull num;
int val,col;
Item() {}
Item(ull _num,int _val,int _col) {
num=_num,val=_val,col=_col;
}
};
namespace Matroid {
const int M=N*2,E=100005,inf=~0U>>1,K=64;
int n,tot,ans,S,T,g[M],v[E],nxt[E],ed,q[E],h,t,d[M],pre[M],w[M],cnt[N];
bool in[M],use[M];
Item item[M];
ull base[K];
inline bool check1() {
for(int i=0; i<tot; i++)if(cnt[i]>1)return 0;
return 1;
}
inline bool check2() {
int i,j;
for(i=0; i<K; i++)base[i]=0;
for(i=0; i<n; i++)if(use[i]) {
ull x=item[i].num;
bool flag=0;
for(j=0; j<K; j++)if(x>>j&1) {
if(!base[j]) {
base[j]=x;
flag=1;
break;
} else x^=base[j];
}
if(!flag)return 0;
}
return 1;
}
inline void add(int x,int y) {
v[++ed]=y;
nxt[ed]=g[x];
g[x]=ed;
}
inline void ext(int x,int y,int z) {
if(d[x]>=y)return;
d[x]=y;
pre[x]=z;
if(in[x])return;
q[++t]=x;
in[x]=1;
}
inline bool find() {
int i,j,S=n+1,T=n+2;
for(ed=i=0; i<=T; i++)g[i]=w[i]=0;
for(i=0; i<n; i++)if(!use[i]) {
w[i]=item[i].val;
use[i]^=1;
cnt[item[i].col]++;
if(check1())add(S,i);
if(check2())add(i,T);
cnt[item[i].col]--;
use[i]^=1;
} else w[i]=-item[i].val;
for(i=0; i<n; i++)if(use[i])for(j=0; j<n; j++)if(!use[j]) {
use[i]^=1,use[j]^=1;
cnt[item[i].col]--;
cnt[item[j].col]++;
if(check1())add(i,j);
if(check2())add(j,i);
cnt[item[i].col]++;
cnt[item[j].col]--;
use[i]^=1,use[j]^=1;
}
for(i=0; i<=T; i++)d[i]=-inf,in[i]=0;
q[h=t=1]=S;
d[S]=0,in[S]=1;
while(h<=t) {
int x=q[h++];
for(i=g[x]; i; i=nxt[i])ext(v[i],d[x]+w[v[i]],x);
in[x]=0;
}
if(d[T]==-inf)return 0;
ans+=d[T];
while(pre[T]!=S) {
T=pre[T];
if(use[T])cnt[item[T].col]--;
else cnt[item[T].col]++;
use[T]^=1;
}
return 1;
}
inline int intersection(const vector<Item>&pool,int _tot) {
int i;
n=ans=0;
tot=_tot;
for(i=0; i<pool.size(); i++) {
if(pool[i].val>=0)item[n++]=pool[i];
else std::cout<<pool[i].num<<" "<<pool[i].val<<" "<<pool[i].val<<'\n';
}
// for(i=0; i<pool.size(); i++)item[n++]=pool[i];
for(i=0; i<tot; i++)cnt[i]=0;
for(i=0; i<n; i++)use[i]=0;
for(i=0; i<tot; i++)if(!find())return -1;
return ans;
}
}
inline void add(int x,int y) {
v[++ed]=y;
nxt[ed]=g[x];
g[x]=ed;
}
void dfs(int x,int y) {
for(int i=g[x]; i; i=nxt[i]) {
int u=v[i];
if(u==y)continue;
dfs(u,x);
}
for(int now=0; now<2; now++) {
int tot=0;
vector<Item>pool;
for(int i=g[x]; i; i=nxt[i]) {
int u=v[i];
if(u==y)continue;
for(int j=0; j<2; j++)pool.push_back(Item(num[u][j],f[u][j][now],tot));
tot++;
}
pool.push_back(Item(num[x][now],val[x][now],tot));
tot++;
if(y) {
for(int fa=0; fa<2; fa++) {
vector<Item>npool=pool;
npool.push_back(Item(num[y][fa],0,tot));
f[x][now][fa]=Matroid::intersection(npool,tot+1);
}
} else {
ans=max(ans,Matroid::intersection(pool,tot));
}
}
}
int main() {
scanf("%d",&Case);
while(Case--) {
scanf("%d",&n);
ans=-1;
for(ed=i=0; i<=n; i++)g[i]=0;
for(i=1; i<=n; i++)for(j=0; j<2; j++)scanf("%llu%d",&num[i][j],&val[i][j]);
for(i=1; i<n; i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(1,0);
printf("%d\n",ans);
}
}
可以简单修改求解拟阵交。
拟阵交板题 2023HDU多校9 1010
#include<bits/stdc++.h>
#include<map>
using namespace std;
const int N = 505;
int n , m;
map<int,vector<pair<int,int>>>E;
map<int,int>limit;
typedef long long ll;
struct uni {
int p[N];
int cnt ;
void init() {
for(int i = 1; i <= n; i++) p[i] = i;
cnt = n;
}
int Find(int x) {
return p[x] == x ? x : p[x] = Find(p[x]) ;
}
bool Merge(int u,int v) {
u = Find(u) , v = Find(v);
if(u == v) return 0;
p[u] = v;
cnt--;
return 1;
}
bool in(int u,int v) {
return Find(u) == Find(v);
}
} Un[N];
struct edge {
int u , v , w;
};
struct Item {
int x,y,col;
ll val;
Item() {}
Item(int _x,int _y,int _col,ll _val) {
x=_x;
y=_y;
col=_col;
val=_val;
}
};
namespace Matroid {
///F1 : connect
///F2 : num limit
const int M=N*2,E=100005;
const ll inf=1e9;
int n,tot,ans,S,T,g[M],v[E],nxt[E],ed,q[E],h,t,d[M],pre[M],w[M];
map<int,int>cnt;
bool in[M],use[M];
Item item[M];
inline void add(int x,int y) {
v[++ed]=y;
nxt[ed]=g[x];
g[x]=ed;
}
inline void ext(int x,int y,int z) {
if(d[x]>=y)return;
d[x]=y;
pre[x]=z;
if(in[x])return;
q[++t]=x;
in[x]=1;
}
inline bool find() {
int i,j,S=n+1,T=n+2;
for(ed=i=0; i<=T; i++)g[i]=w[i]=0;
for(int i = 0; i < n; i++) {//维护所有的I+{x}
if(!use[i]) {
Un[i].init() ;
for(int j = 0; j < n; j++) {
if(i != j&&(!use[j])) Un[i].Merge(item[j].x , item[j].y);
}
}
}
for(i=0; i<n; i++)if(!use[i]) {
w[i]=item[i].val;
use[i]^=1;
cnt[item[i].col]++;
if(Un[i].cnt == 1)add(S,i);//I+{i}\in F1
if(cnt[item[i].col]<=limit[item[i].col])add(i,T);//I+{i}\in F2
cnt[item[i].col]--;
use[i]^=1;
} else w[i]=-item[i].val;
for(i=0; i<n; i++)if(use[i])for(j=0; j<n; j++)if(!use[j]) {
use[i]^=1,use[j]^=1;
cnt[item[i].col]--;
cnt[item[j].col]++;
if(Un[j].cnt == 1 || (Un[j].cnt == 2 && (!Un[j].in(item[i].x,item[i].y))))add(i,j);//I-{i}+{j}\in F1
if(cnt[item[j].col]<=limit[item[j].col])add(j,i);//I-{i}+{j}\in F2
cnt[item[i].col]++;
cnt[item[j].col]--;
use[i]^=1,use[j]^=1;
}
for(i=0; i<=T; i++)d[i]=-inf,in[i]=0;
q[h=t=1]=S;
d[S]=0,in[S]=1;
while(h<=t) {
int x=q[h++];
for(i=g[x]; i; i=nxt[i])ext(v[i],d[x]+w[v[i]],x);
in[x]=0;
}
if(d[T]==-inf)return 0;
ans+=d[T];
while(pre[T]!=S) {
T=pre[T];
if(use[T])cnt[item[T].col]--;
else cnt[item[T].col]++;
use[T]^=1;
}
return 1;
}
inline int intersection(const vector<Item>&pool,int _tot) {//finished
int i;
n=ans=0;
tot=_tot;
for(i=0; i<pool.size(); i++) {
item[n++]=pool[i];
}
// for(i=0; i<pool.size(); i++)item[n++]=pool[i];
cnt.clear();
for(i=0; i<n; i++)use[i]=0;
for(i=0; i<tot; i++)if(!find())return -1;
return ans;
}
}
vector<Item>edge_S;
bool chk(ll lm) {//finished
limit.clear();
int sum = 0;
for(auto it = E.begin(); it != E.end(); ++it) {
const int& w = it->first;
const vector<pair<int, int>>& v = it->second;
limit[w] = max(0LL, (ll)v.size() - lm / (ll)w);
sum += limit[w];
}
if(Matroid::intersection(edge_S,sum)!=-1)return 1;
else return 0;
}
int t;
void solve() {//finished
cin >> n >> m;
E.clear();
edge_S.clear();
ll r = 0;
for(int i = 1; i <= m; i++) {
int u , v , w;
cin >> u >> v >> w;
E[w].push_back(pair<int,int> {u , v});
r = max(r , (ll)(1LL*w*E[w].size()));
edge_S.push_back(Item(u,v,w,1));
// if(t==54&&i==1)cout<<u<<" "<<v<<" "<<w<<'\n';
}
ll l = 1;
while(l < r-1) {
ll md = ((l + r) >> 1);
if(chk(md)) {
r = md;
} else {
l = md+1;
}
}
if(chk(l))
cout << l << '\n';
else cout<<r<<'\n';
// cout<<n<<" "<<m<<'\n';
}
int main() {//finished
// freopen("01.in","rt",stdin);
// freopen("01.out","wt",stdout);
ios::sync_with_stdio(false) ;
cin.tie(0) ;
cout.tie(0);
cin >> t;
while(t--) {
solve();
}
cout<<clock();
return 0;
}
/*
3
4 4
1 2 1
2 3 1
3 4 2
4 1 2
5 6
1 2 2
2 3 1
1 5 3
1 2 1
4 5 2
4 3 3
2 2
1 2 10
2 1 1
*/