• 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
    ", 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
    ", 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
    ", 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
    ");
                continue;
            }
            int minsum = prim();
            int should = (n-1)/2;
            //printf("minsum = %d
    ", minsum);
            if (minsum <= should) {
                solveprim(should-minsum);
            } else {
                printf("-1
    ");
                continue;
            }
        }
        return 0;
    }
  • 相关阅读:
    logstash入门
    Gray Code LeetCode 89
    Longest Valid Parentheses Leetcode 32 一种奇特的解法
    写一个播放视频文件的ActiveX控件——MFC版(原创)
    一种用于网络播放的ActiveX控件
    《COM原理与应用》学习笔记——一个简单的COM组件的实现
    《COM原理与应用》学习笔记——COM的实现
    《COM原理与应用》题外话——C++虚函数表和delete this
    《COM原理与应用》学习笔记二——COM对象和COM接口的实现
    《COM原理与应用》学习笔记一
  • 原文地址:https://www.cnblogs.com/shinecheng/p/3770107.html
Copyright © 2020-2023  润新知