CodeForces 141E: ...(最小生成树)

[条件转换] 两两之间有且只有一条简单路径<==>树

题意:一个图中有两种边,求一棵生成树,使得这棵树中的两种边数量相等。

思路:

可以证明,当边的权是0或1时,可以生成最小生成树到最大生成树之间的任意值的生成树。

那么,方法就是生成最小生成树,然后,尽量替换0边,使得其成为值为(n-1)/2的生成树。

代码:

写的很乱,没有条理。还是应当先写出流程伪码后再敲代码的。

#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
#define PB push_back
#define N 1020
struct Edge{
    int to;
    int cost;
    int id;
    Edge(int a = 0, int b = 0, int c = 0): to(a), cost(b), id(c){};
};
vector<Edge> e[N];

int n, m;

int dis[N];
int vis[N];
struct Node{
    int cost;
    int id;
    int edgeid;
    Node(int a=0, int b=0, int c=0):cost(a),id(b),edgeid(c){}
    bool operator < (const Node &b) const {
        return cost > b.cost;
    }
};
priority_queue<Node> que;

int prim() {
    while(!que.empty()) que.pop();
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[1] = 0;
    que.push(Node(0,1,0));
    int sum = 0;
    while (!que.empty()) {
        int nowcost = que.top().cost;
        int nowid = que.top().id;
        int nowedgeid = que.top().edgeid;
        que.pop();
        if (vis[nowid]) continue;

        //printf("(%d) ", nowedgeid);
        sum += nowcost;
        vis[nowid] = true;

        for (int i = 0; i < e[nowid].size(); i++) {
            int to = e[nowid][i].to;
            int cost = e[nowid][i].cost;
            if (vis[to]) continue;
            if (dis[to] > cost) {
                dis[to] = cost;
                que.push(Node(cost, to, e[nowid][i].id));
            }
        }
    }
    return sum;
}

void solveprim(int changetime) {
    //printf("changetime = %d\n", changetime);
    vector<int> edgeids;
    while(!que.empty()) que.pop();
    memset(dis,0x3f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    dis[1] = 0;
    que.push(Node(0,1,0));
    int sum = 0;
    while (!que.empty()) {
        int nowcost = que.top().cost;
        int nowid = que.top().id;
        int nowedgeid = que.top().edgeid;
        que.pop();
        if (vis[nowid]) continue;

        if (nowedgeid != 0) {
            if (changetime > 0 && nowcost == 0) {
                bool change = false;
                for (int i = 0; i < e[nowid].size(); i++) {
                    int to = e[nowid][i].to;
                    int cost = e[nowid][i].cost;
                    if (vis[to] && cost == 1) {
                        changetime--;
                        //printf("change! %d\n", e[nowid][i].id);
                        edgeids.push_back(e[nowid][i].id);
                        change = true;
                        break;
                    }
                }
                if (!change) {
                    edgeids.push_back(nowedgeid);
                }
            } else {
                edgeids.push_back(nowedgeid);
            }
        }
        sum += nowcost;
        vis[nowid] = true;

        for (int i = 0; i < e[nowid].size(); i++) {
            int to = e[nowid][i].to;
            int cost = e[nowid][i].cost;
            if (vis[to]) continue;
            if (dis[to] > cost) {
                dis[to] = cost;
                que.push(Node(cost, to, e[nowid][i].id));
            }
        }
    }

    if (changetime != 0) puts("-1");
    else {
        printf("%d\n", edgeids.size());
        for (int i = 0; i < edgeids.size(); i++) {
            printf("%d ", edgeids[i]);
        }puts("");
    }
    return ;
}


int main() {
    while (scanf("%d%d", &n, &m) != EOF) {
        for (int i = 0; i <= n; i++) {
            e[i].clear();
        }
        for (int i = 1; i <= m; i++) {
            int u, v;
            char type[20];
            scanf("%d%d%s", &u, &v, type);
            if (u == v) continue;
            e[u].PB(Edge(v, type[0] == 'S', i));
            e[v].PB(Edge(u, type[0] == 'S', i));
        }
        if (n%2 == 0) {
            printf("-1\n");
            continue;
        }
        int minsum = prim();
        int should = (n-1)/2;
        //printf("minsum = %d\n", minsum);
        if (minsum <= should) {
            solveprim(should-minsum);
        } else {
            printf("-1\n");
            continue;
        }
    }
    return 0;
}

 

posted on 2014-06-05 12:50  ShineCheng  阅读(550)  评论(0编辑  收藏  举报

导航