[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;
}