uva 11098 - Battle II(强联通)

题目链接:uva 11098 - Battle II


先将图缩点,每个强连通分量中最小的点权做为新点的点权。所有入度为0的点是一定要的,然后从点权小的开始考虑,如果加入后平均值变小,则加入。最后按照dfs序排序后输出。


#include <cstdio>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>

using namespace std;
typedef long long ll;
const int maxn = 305;
const ll inf = 0x3f3f3f3f3f3f3f3f;

int N, X[maxn], Y[maxn], R[maxn], E[maxn];
int cntlock, cntscc, sccno[maxn], pre[maxn];
vector<int> G[maxn], T[maxn];
stack<int> S;

struct State {
	int pre, idx;
	ll val;
	State(int pre = 0, int idx = 0, ll val = 0): pre(pre), idx(idx), val(val) {}
};

inline bool cmpVal(const State& a, const State& b) { return a.val < b.val; }
inline bool cmpIdx(const State& a, const State& b) { return a.pre < b.pre; }

int dfs (int u) {
	int lowu = pre[u] = ++cntlock;
	S.push(u);

	for (int i = 0; i < G[u].size(); i++) {
		int v = G[u][i];
		if (!pre[v]) {
			int lowv = dfs(v);
			lowu = min(lowu, lowv);
		} else if (!sccno[v])
			lowu = min(lowu, pre[v]);
	}

	if (lowu == pre[u]) {
		cntscc++;
		while (true) {
			int x = S.top(); S.pop();
			sccno[x] = cntscc;
			if (x == u) break;
		}
	}
	return lowu;
}

void findSCC() {
	cntlock = cntscc = 0;
	memset(pre, 0, sizeof(pre));
	memset(sccno, 0, sizeof(sccno));
	for (int i = 0; i < N; i++)
		if (!pre[i]) dfs(i);
}

inline ll distance(ll a, ll b) { return a * a + b * b; }

bool judge (int a, int b) {
	ll c = distance((ll)X[a]-X[b], (ll)Y[a]-Y[b]);
	ll d = (R[a] + R[b] + E[a]); d = d * d;
	return d >= c;
}

void init () {
	scanf("%d", &N);
	for (int i = 0; i < N; i++)
		scanf("%d%d%d%d", &X[i], &Y[i], &R[i], &E[i]);

	for (int i = 0; i < N; i++) {
		G[i].clear();
		for (int j = 0; j < N; j++) if (i != j)
			if (judge(i, j)) G[i].push_back(j);
	}
	findSCC();
}

void solve () {
	ll C[maxn], sum = 0;
	int in[maxn], rec[maxn];
	memset(in, 0, sizeof(in));
	for (int i = 1; i <= cntscc; i++)
		C[i] = inf, T[i].clear();

	for (int i = 0; i < N; i++) {
		int u = sccno[i];
		if (C[u] > E[i]) {
			C[u] = E[i];
			rec[u] = i;
		}

		for (int j = 0; j < G[i].size(); j++) {
			int v = sccno[G[i][j]];
			if (u != v) {
				T[v].push_back(u);
				in[u]++;
			}
		}
	}


	int p = 0, c = 0;
	queue<int> que;
	vector<State> ans, tmp;
	for (int i = 1; i <= cntscc; i++) if (!in[i]) que.push(i);
	while (!que.empty()) {
		int u = que.front();
		que.pop();
		pre[u] = cntlock++;
		if (T[u].size() == 0) {
			ans.push_back(State(p++, rec[u], C[u]));
			sum += C[u], c++;
		} else
			tmp.push_back(State(p++, rec[u], C[u]));

		for (int i = 0; i < T[u].size(); i++) {
			int v = T[u][i];
			in[v]--;
			if (in[v] == 0) que.push(v);
		}
	}

	sort(tmp.begin(), tmp.end(), cmpVal);
	p = 0;
	while (p < tmp.size()) {
		if (tmp[p].val * c >= sum) break;
		ans.push_back(tmp[p]);
		sum += tmp[p].val;
		c++, p++;
	}

	sort(ans.begin(), ans.end(), cmpIdx);
	for (int i = 0; i < ans.size(); i++)
		printf(" %d", ans[i].idx);
	printf("\n");
}

int main () {
	int cas;
	scanf("%d", &cas);
	for (int kcas = 1; kcas <= cas; kcas++) {
		init();
		printf("Case #%d:", kcas);
		solve();
	}
	return 0;
}


你可能感兴趣的:(uva 11098 - Battle II(强联通))