[BZOJ 2115][WC 2011]Xor
题意
- 给定一个n个点m条边的无向图,求一条路径使得路径的异或和最大
分析
- 随便搞出一条路径
- 考虑环,路径^环=路径,相当于我们从环的另一侧走过去,考虑两条路径,路径^路径=环
- 然后找到图中所有的环分别求xor,最后判定取哪些环能使答案最大。
- 进行高斯消元,用拟阵证明取线性基的正确性
Code
#include <bits/stdc++.h>
using namespace std;
#define N 50010
#define M 200010
typedef long long ll;
struct Edge{
int to, next;
ll w;
}edge[M];
int cnt, h[N], n, m;
void add(int u, int v, ll w){
cnt ++;
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = h[u];
h[u] = cnt;
swap(u, v);
cnt ++;
edge[cnt].to = v;
edge[cnt].w = w;
edge[cnt].next = h[u];
h[u] = cnt;
}
ll d[N], a[M], num;
bool vis[N];
void dfs(int x){
vis[x] = 1;
for(int i = h[x]; i; i = edge[i].next){
int y = edge[i].to;
if(!vis[y]) d[y] = d[x] ^ edge[i].w, dfs(y);
else a[++ num] = d[y] ^ d[x] ^ edge[i].w;
}
}
int gauss(){
int k = 1;
for(int p = 63; p >= 0; p --){
int t = 0;
for(int i = k; i <= num; i ++)
if(a[i] >> p & 1){t = i; break;}
if(t){
swap(a[t], a[k]);
for(int i = 1; i <= num; i ++)
if(i != k && (a[i] >> p & 1))
a[i] ^= a[k];
k ++;
}
}
return k - 1;
}
int main(){
scanf("%d%d", &n, &m);
int u, v; ll w;
for(int i = 1; i <= m; i ++){
scanf("%d%d%lld", &u, &v, &w);
add(u, v, w);
}
dfs(1);
int cnt = gauss();
ll ans = d[n];
for(int i = 1; i <= cnt; i ++)
if((ans ^ a[i]) > ans)
ans ^= a[i];
printf("%lld\n", ans);
return 0;
}
[BZOJ 2460][BeiJing2011]元素
题意:
- 给定一些元素,每个元素有两个值a和b,现在需要选出一些元素,在不存在a值异或和为0的子集的情况下使b之和最大
分析
#include <bits/stdc++.h>
#define maxn 1010
using namespace std;
typedef long long ll;
struct Point{
ll a;
int b;
bool operator<(const Point& k)const{
return b > k.b;
}
}p[maxn];
int n;
ll ans, base[maxn];
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i ++)
scanf("%lld%d", &p[i].a, &p[i].b);
sort(p+1, p+1+n);
for(int i = 1; i <= n; i ++){
for(int j = 63; ~j; j --){
if(p[i].a >> j & 1){
if(!base[j]){
base[j] = p[i].a;
break;
}
p[i].a ^= base[j];
}
}
if(p[i].a)ans += p[i].b;
}
printf("%lld\n", ans);
return 0;
}
[BZOJ 4004][JLOI2015]装备购买
题意:
- 有一个人买一些装备,要求线性无关,求买装备最多而且花费最少
分析:
#include <bits/stdc++.h>
#define maxn 510
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
struct Node{
int a[maxn], c;
bool operator<(const Node& k)const{return c < k.c;}
}p[maxn], bases[maxn];
bool bases_flag[maxn];
int n, m;
ll power_mod(ll a, ll b, ll mod){
ll ret = 1;
while(b){
if(b & 1)ret = ret * a % mod;
b >>= 1;
a = a * a % mod;
}return ret;
}
void Gauss(Node& a, const Node& b, int o){
ll t = mod - a.a[o] * power_mod(b.a[o], mod-2, mod) % mod;
for(int i = o; i <= m; i ++)
a.a[i] =(a.a[i] + b.a[i] * t) % mod;
}
bool Insert(int pos){
for(int i = 1; i <= m; i ++){
if(p[pos].a[i]){
if(!bases_flag[i]){
bases[i] = p[pos];
bases_flag[i] = true;
return true;
}
Gauss(p[pos], bases[i], i);
}
}
return false;
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
scanf("%d", &p[i].a[j]);
for(int i = 1; i <= n; i ++)
scanf("%d", &p[i].c);
sort(p+1, p+1+n);
long long ans = 0;
int cnt = 0;
for(int i = 1; i <= n; i ++)
if(Insert(i))ans += p[i].c, cnt ++;
printf("%d %lld\n", cnt, ans);
return 0;
}