|
亲!马上注册或者登录会查看更多内容!
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
1001 Battle Over Cities - Hard Version
N个城市,之前有道路相连,有些道路是坏的,修路需要代价。如果一个城市被占领,则所有和它关联的道路都关闭。目标是:选择最重要的(若干)城市——如果它被占领,我们需要很大的修路代价把其他城市连起来。
分析: 问题虽然说了原来图保证连通,但有可能原来就是一个树了,这样占领一些城市,可能会导致,我们根本无法连接剩余城市,这种代价要按照无穷大计算…… 坑就在这里。这个题说白了就是一个kruskal算法的最小生成树问题。 Top level也不太难。
- #include <cstdio>
- #include <cstring>
- #include <string>
- #include <vector>
- #include <algorithm>
- using namespace std;
- struct node {
- int x;
- int y;
- int c;
- };
- int f[505], num[505];
- vector<node> e;
- bool cmp(const node &x, const node &y) {
- return x.c < y.c;
- }
- int getf(int x) {
- return (f[x] == x)?x:(f[x] = getf(f[x]));
- }
- bool make(int x,int y) {
- if ((x = getf(x)) == (y = getf(y))) {
- return false;
- }
- if (num[x] < num[y]) {
- f[x] = y;
- num[y] += num[x];
- }
- else {
- f[y] = x;
- num[x] += num[y];
- }
- return true;
- }
- int main() {
- int n, m;
- scanf("%d%d",&n,&m);
- for (int i = 0; i < m; ++i) {
- int x, y, c, p;
- scanf("%d%d%d%d",&x, &y, &c, &p);
- node temp;
- temp.x = x - 1;
- temp.y = y - 1;
- temp.c = p?0:c;
- e.push_back(temp);
- }
- sort(e.begin(), e.end(), cmp);
- vector<int> answer;
- int now = 1;
- bool mark = false;
- for (int i = 0; i < n; ++i) {
- int need = n - 2;
- int cost = 0;
- for (int j = 0; j < n; ++j) {
- f[j] = j;
- num[j] = 1;
- }
- for (int j = 0; (need > 0) && (j < m); ++j) {
- if ((e[j].x != i) && (e[j].y != i) && make(e[j].x, e[j].y)) {
- --need;
- cost += e[j].c;
- }
- }
- if (need > 0) {
- if (!mark) {
- mark = true;
- answer.clear();
- }
- answer.push_back(i);
- }
- else if (mark) {
- }
- else if (cost > now) {
- now = cost;
- answer.resize(1);
- answer[0] = i;
- }
- else if (cost == now) {
- answer.push_back(i);
- }
- }
- if (answer.empty()) {
- puts("0");
- }
- else {
- for (int i = 0; i < answer.size(); ++i) {
- if (i) {
- putchar(' ');
- }
- printf("%d",answer【i】 + 1);
- }
- puts("");
- }
- return 0;
- }
复制代码
|
|