HDU5627--Clarke and MST (bfs+位运算)

http://www.cnblogs.com/wenruo/p/5188495.html

Clarke and MST

Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
克拉克是一名人格分裂患者。某一天克拉克变成了一名图论研究者。  
他学习了最小生成树的几个算法,于是突发奇想,想做一个位运算and的最大生成树。  
一棵生成树是由n−1条边组成的,且n个点两两可达。一棵生成树的大小等于所有在生成树上的边的权值经过位运算and后得到的数。 现在他想找出最大的生成树。
输入描述
第一行是一个整数T(1≤T≤5),表示数据组数。 每组数据第一行是两个整数n,m(1≤n,m≤300000),分别表示点个数和边个数。其中n,m>100000n, 的数据最多一组。 接下来m行,每行3个整数x,y,w(1≤x,y≤n,0≤w≤109)9​​),表示x,yx, yx,y之间有一条大小为www的边。
输出描述
每组数据输出一行一个数,表示答案。若不存在生成树,输出000。
输入样例
1
4 5
1 2 5
1 3 3
1 4 2
2 3 1
3 4 7
输出样例
1

题解:

我们贪心的从大到小枚举每一个位,如果一个位能取当且仅当所有权值这个位不为0的边能形成一棵生成树。是否能形成生成树我们简单的bfs一下就行了。

代码:

#include <bits/stdc++.h>
#define clr(x,c) memset(x,c,sizeof(x))
using namespace std;

int Scan() {
    int res = 0, flag = 0;
    char ch;
    if((ch = getchar()) == '-') flag = 1;
    else if(ch >= '0' && ch <= '9') res = ch - '0';
    while((ch = getchar()) >= '0' && ch <= '9')
        res = res * 10 + (ch - '0');
    return flag ? -res : res;
}

const int N = 300005;
struct Edge {
	int to;
	int w;
	Edge(int to = 0, int w = 0) : to(to), w(w){}
} edge[N];
vector<Edge> G[N];

bool vis[N];
int n, m;
int now;

bool bfs()
{
    queue<int> q;
    clr(vis, false);
    q.push(1);
    vis[1] = true;
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (unsigned i = 0; i < G[u].size(); ++i) {
            int v = G[u][i].to;
            int w = G[u][i].w;
            if (!vis[v] && (w & now) == now) {
                vis[v] = true;
                q.push(v);
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        if (!vis[i]) return false;
    }
    return true;
}

int main()
{
	int t = Scan();
	while (t--) {
		n = Scan(); m = Scan();
		for (int i = 1; i <= n; ++i)
            G[i].clear();
		int x, y, w;
		for (int i = 0; i < m; ++i) {
			x = Scan(); y = Scan(); w = Scan();
			G[x].push_back(Edge(y, w));
			G[y].push_back(Edge(x, w));
		}
		int ans = 0;
		for (int i = 30; i >= 0; --i) {
			now = ((1 << i) | ans);
			if (bfs()) ans = now;
		}
		printf("%d\n", ans);
	}

	return 0;
}

 

开始用链式前向星一直T啊,555~是我写挫了还是链式前向星本身比较慢………

你可能感兴趣的:(HDU5627--Clarke and MST (bfs+位运算))