Clarke and MST
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 165 Accepted Submission(s): 85
Problem Description
Clarke is a patient with multiple personality disorder. One day he turned into a learner of graph theory.
He learned some algorithms of minimum spanning tree. Then he had a good idea, he wanted to find the maximum spanning tree with bit operation AND.
A spanning tree is composed by n−1 edges. Each two points of n points can reach each other. The size of a spanning tree is generated by bit operation AND with values of n−1 edges.
Now he wants to figure out the maximum spanning tree.
He learned some algorithms of minimum spanning tree. Then he had a good idea, he wanted to find the maximum spanning tree with bit operation AND.
A spanning tree is composed by n−1 edges. Each two points of n points can reach each other. The size of a spanning tree is generated by bit operation AND with values of n−1 edges.
Now he wants to figure out the maximum spanning tree.
Input
The first line contains an integer
T(1≤T≤5)
, the number of test cases.
For each test case, the first line contains two integers n,m(2≤n≤300000,1≤m≤300000) , denoting the number of points and the number of edge respectively.
Then m lines followed, each line contains three integers x,y,w(1≤x,y≤n,0≤w≤109) , denoting an edge between x,y with value w .
The number of test case with n,m>100000 will not exceed 1.
For each test case, the first line contains two integers n,m(2≤n≤300000,1≤m≤300000) , denoting the number of points and the number of edge respectively.
Then m lines followed, each line contains three integers x,y,w(1≤x,y≤n,0≤w≤109) , denoting an edge between x,y with value w .
The number of test case with n,m>100000 will not exceed 1.
Output
For each test case, print a line contained an integer represented the answer. If there is no any spanning tree, print 0.
Sample Input
1 4 5 1 2 5 1 3 3 1 4 2 2 3 1 3 4 7
Sample Output
1
题意:求最大and生成树,不存在输出0。
思路:贪心枚举二进制位。 还有一个思路不知道对不对,试试AC了。。。估计是数据水。随便建立一棵MST,求出and值。然后加入新边<u, v>,去掉<u, v>在MST中权值最小的边,再更新and值。。。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF (2000000000+10)
#define eps 1e-8
#define MAXN (300000+10)
#define MAXM (600000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#pragma comment(linker, "/STACK:102400000,102400000")
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
int u[MAXN], v[MAXN], w[MAXN];
int pre[MAXN];
void init(int n){for(int i = 1; i <= n; i++) pre[i] = i;}
int Find(int p){
int child = p; int t;
while(p != pre[p]) p = pre[p];
while(child != p) {t = pre[child]; pre[child] = p; child = t;}
return p;
}
int main()
{
int t; Ri(t);
W(t)
{
int n, m; Ri(n); Ri(m);
for(int i = 0; i < m; i++)
Ri(u[i]), Ri(v[i]), Ri(w[i]);
int ans = 0;
for(int bit = 30; bit >= 0; bit--)
{
init(n); ans |= (1<<bit);
for(int i = 0; i < m; i++)
if((w[i] & ans) == ans)
if(Find(u[i]) != Find(v[i]))
pre[Find(u[i])] = Find(v[i]);
bool flag = true; int cnt = 0;
for(int i = 1; i <= n; i++)
{
if(pre[i] == i) cnt++;
if(cnt > 1) {flag = false; break;}
}
if(!flag) ans ^= (1<<bit);
}
Pi(ans);
}
return 0;
}
不知道对不对的思路:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF (2000000000+10)
#define eps 1e-8
#define MAXN (300000+10)
#define MAXM (600000+10)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while((a)--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
#pragma comment(linker, "/STACK:102400000,102400000")
#define fi first
#define se second
using namespace std;
typedef pair<int, int> pii;
int N, M;
struct LCA
{
struct Edge{
int from, to, val, next;
};
Edge edge[MAXM];
int head[MAXN], edgenum;
int depth[MAXN], fa[MAXN][20], Mx[MAXN][20];
void init(){
edgenum = 0;
CLR(head, -1);
}
void addEdge(int u, int v, int w)
{
Edge E = {u, v, w, head[u]};
edge[edgenum] = E;
head[u] = edgenum++;
}
void DFS(int u, int f, int d)
{
depth[u] = d; fa[u][0] = f;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == f)
{
Mx[u][0] = edge[i].val;
continue;
}
DFS(v, u, d+1);
}
}
void LCA_init()
{
DFS(1, -1, 0);
for(int i = 1; i < 20; i++)
{
for(int j = 1; j <= N; j++)
{
fa[j][i] = fa[fa[j][i-1]][i-1];
Mx[j][i] = min(Mx[j][i-1], Mx[fa[j][i-1]][i-1]);
}
}
}
int Get_path_min(int u, int v)
{
int ans = INF;
while(depth[u] != depth[v])
{
if(depth[u] < depth[v])
swap(u, v);
int d = depth[u] - depth[v];
for(int i = 0; i < 20; i++)
{
if(d >> i & 1)
{
ans = min(ans, Mx[u][i]);
u = fa[u][i];
}
}
}
if(u == v)
return ans;
for(int i = 19; i >= 0; i--)
{
if(fa[u][i] != fa[v][i])
{
ans = min(ans, Mx[u][i]);
ans = min(ans, Mx[v][i]);
u = fa[u][i];
v = fa[v][i];
}
}
return min(ans, min(Mx[u][0], Mx[v][0]));
}
};
LCA L;
struct Union
{
int pre[MAXN];
void init()
{
for(int i = 1; i <= N; i++)
pre[i] = i;
}
int Find(int p)
{
int child = p;
while(p != pre[p]) p = pre[p];
while(child != p)
{
int t = pre[child];
pre[child] = p;
child = t;
}
return p;
}
};
Union U;
struct Node{
int u, v, w;
};
Node num[MAXM];
bool cmp(Node a, Node b){
return a.w < b.w;
}
int a[MAXN], b[MAXN], c[MAXN];
int cnt[40];
void solve(int v, int op)
{
for(int i = 30; i >= 0; i--)
{
if(v & (1 << i))
{
if(op == 1)
cnt[i]++;
else
cnt[i]--;
}
}
}
int Count()
{
int ans = 0;
for(int i = 30; i >= 0; i--)
{
if(cnt[i] == N-1)
ans |= (1 << i);
}
return ans;
}
int main()
{
int t; Ri(t);
W(t)
{
Ri(N); Ri(M);
U.init(); L.init();
int top = 0;
for(int i = 1; i <= M; i++)
{
Ri(a[i]); Ri(b[i]); Ri(c[i]);
num[top].u = a[i]; num[top].v = b[i]; num[top++].w = c[i];
}
sort(num, num+top, cmp); CLR(cnt, 0);
for(int i = 0; i < top; i++)
{
int u = U.Find(num[i].u);
int v = U.Find(num[i].v);
if(u != v)
{
L.addEdge(num[i].u, num[i].v, num[i].w);
L.addEdge(num[i].v, num[i].u, num[i].w);
solve(num[i].w, 1);
U.pre[u] = v;
}
}
bool flag = true; int temp = 0;
for(int i = 1; i <= N; i++)
{
if(U.pre[i] == i)
temp++;
if(temp > 1)
{
flag = false;
break;
}
}
if(!flag)
{
printf("0\n");
continue;
}
int ans = Count();
L.LCA_init();
for(int i = 1; i <= M; i++)
{
int Min = L.Get_path_min(a[i], b[i]);
solve(c[i], 1); solve(Min, -1);
ans = max(ans, Count());
}
Pi(ans);
}
return 0;
}