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

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

思路:

可以证明,当边的权是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 = , int b = , int c = ): 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=, int b=, int c=):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,,sizeof(vis));
dis[] = ;
que.push(Node(,,));
int sum = ;
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 = ; 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,,sizeof(vis));
dis[] = ;
que.push(Node(,,));
int sum = ;
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 != ) {
if (changetime > && nowcost == ) {
bool change = false;
for (int i = ; i < e[nowid].size(); i++) {
int to = e[nowid][i].to;
int cost = e[nowid][i].cost;
if (vis[to] && cost == ) {
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 = ; 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 != ) puts("-1");
else {
printf("%d\n", edgeids.size());
for (int i = ; i < edgeids.size(); i++) {
printf("%d ", edgeids[i]);
}puts("");
}
return ;
} int main() {
while (scanf("%d%d", &n, &m) != EOF) {
for (int i = ; i <= n; i++) {
e[i].clear();
}
for (int i = ; i <= m; i++) {
int u, v;
char type[];
scanf("%d%d%s", &u, &v, type);
if (u == v) continue;
e[u].PB(Edge(v, type[] == 'S', i));
e[v].PB(Edge(u, type[] == 'S', i));
}
if (n% == ) {
printf("-1\n");
continue;
}
int minsum = prim();
int should = (n-)/;
//printf("minsum = %d\n", minsum);
if (minsum <= should) {
solveprim(should-minsum);
} else {
printf("-1\n");
continue;
}
}
return ;
}

CodeForces 141E: ...(最小生成树)的更多相关文章

  1. codeForces 472D 最小生成树

    题目大意:给出一个图中点的两两距离,问是否是一棵树,若是,求出平均边权最大的点 prim最小生成树,若原图是树,则最小生成树的距离就是原距离.否则不是. 搞出来树了,第二问随便dfs就好了. #inc ...

  2. Xor-MST CodeForces - 888G (最小生成树,分治)

    大意: n结点无向完全图, 给定每个点的点权, 边权为两端点异或值, 求最小生成树

  3. Mobile Phone Network CodeForces - 1023F (最小生成树)

    大意: 无向图, 其中k条边是你的, 边权待定, m条边是你对手的, 边权已知. 求如何设置边权能使最小生成树中, 你的边全被选到, 且你的边的边权和最大. 若有多棵最小生成树优先取你的边. 先将$k ...

  4. The Shortest Statement CodeForces - 1051F 最小生成树+并查集+LCA

    题目描述 You are given a weighed undirected connected graph, consisting of n vertices and mm edges. You ...

  5. Abandoning Roads CodeForces - 1149D (最小生成树)

    大意: 给定无向图, 边权只有两种, 对于每个点$x$, 输出所有最小生成树中, 点$1$到$x$的最短距离. 先将边权为$a$的边合并, 考虑添加边权为$b$的边. 每条路径只能经过每个连通块一次, ...

  6. @codeforces - 141E@ Clearing Up

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N 个点 M 条边的图,每条为黑色或者白色. 现在让你 ...

  7. 正睿OI国庆DAY2:图论专题

    正睿OI国庆DAY2:图论专题 dfs/例题 判断无向图之间是否存在至少三条点不相交的简单路径 一个想法是最大流(后来说可以做,但是是多项式时间做法 旁边GavinZheng神仙在谈最小生成树 陈主力 ...

  8. Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)

    题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...

  9. 【最小生成树】Codeforces 707B Bakery

    题目链接: http://codeforces.com/problemset/problem/707/B 题目大意: 给你N个点M条无向边,其中有K个面粉站,现在一个人要在不是面粉站的点上开店,问到面 ...

随机推荐

  1. 如何用纯 CSS 和 D3 创作一艘遨游太空的宇宙飞船

    效果预览 在线演示 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/oMqNmv 可交互视频 ...

  2. vue 使用lib-flexable,px2rem 进行移动端适配 但是引入的第三方UI组件 vux 的样式缩小,解决方案

    最近在写移动端项目,就想用lib-flexable,px2rem来进行适配,把px转换成rem但是也用到了第三方UI组件库vux,把这个引入发现一个问题就是vux的组件都缩小了,在网上找不到答案,最后 ...

  3. 使用 Python 编写登陆接口

    # 使用 Python 编写登陆接口# Create Date: 2017.10.31 Tuesday# Author: Eric Zhao# -*- coding:utf-8 -*-'''编写登陆接 ...

  4. perl-basic-数组操作

    RT...直接看代码 my @stack = ("Fred", "Eileen", "Denise", "Charlie" ...

  5. ACM-ICPC 2018 徐州赛区网络预赛 I. Characters with Hash

    Mur loves hash algorithm, and he sometimes encrypt another one's name, and call him with that encryp ...

  6. virtual function c++

    之前一直不明白为什么要用虚函数,我只知道这样的规则, Base b = new derived(); b->do(); 调用的是子类的do(): virtue class只是一个虚拟的,调用的是 ...

  7. python multiprocessing 源码分析

    1. 文档是最先需要了解的,读完文档可能会有很多的意外的收获同时也会留下疑惑,对于一般的使用我觉得读完文档就差不多了,除非一些很有疑惑的地方你可能需要再深入的了解一下.我读文档的目的第一个就是为了找出 ...

  8. Selenium WebDriver-操作复选框

    #encoding=utf-8 import unittest import time import chardet from selenium import webdriver class Visi ...

  9. python学习-- 在for循环中还有很多有用的东西,如下:

    变量 描述 forloop.counter 索引从 1 开始算 forloop.counter0 索引从 0 开始算 forloop.revcounter 索引从最大长度到 1 forloop.rev ...

  10. FastText 介绍

    FastText 介绍 在面试百度的NLP工程师时,被问及常用的词向量表示学习方法有哪些,我说知道word2vec,然后大佬又问我知道FastText么... 这就很尴尬了,不会! 不同于word2v ...