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 = , 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: ...(最小生成树)的更多相关文章
- codeForces 472D 最小生成树
题目大意:给出一个图中点的两两距离,问是否是一棵树,若是,求出平均边权最大的点 prim最小生成树,若原图是树,则最小生成树的距离就是原距离.否则不是. 搞出来树了,第二问随便dfs就好了. #inc ...
- Xor-MST CodeForces - 888G (最小生成树,分治)
大意: n结点无向完全图, 给定每个点的点权, 边权为两端点异或值, 求最小生成树
- Mobile Phone Network CodeForces - 1023F (最小生成树)
大意: 无向图, 其中k条边是你的, 边权待定, m条边是你对手的, 边权已知. 求如何设置边权能使最小生成树中, 你的边全被选到, 且你的边的边权和最大. 若有多棵最小生成树优先取你的边. 先将$k ...
- The Shortest Statement CodeForces - 1051F 最小生成树+并查集+LCA
题目描述 You are given a weighed undirected connected graph, consisting of n vertices and mm edges. You ...
- Abandoning Roads CodeForces - 1149D (最小生成树)
大意: 给定无向图, 边权只有两种, 对于每个点$x$, 输出所有最小生成树中, 点$1$到$x$的最短距离. 先将边权为$a$的边合并, 考虑添加边权为$b$的边. 每条路径只能经过每个连通块一次, ...
- @codeforces - 141E@ Clearing Up
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N 个点 M 条边的图,每条为黑色或者白色. 现在让你 ...
- 正睿OI国庆DAY2:图论专题
正睿OI国庆DAY2:图论专题 dfs/例题 判断无向图之间是否存在至少三条点不相交的简单路径 一个想法是最大流(后来说可以做,但是是多项式时间做法 旁边GavinZheng神仙在谈最小生成树 陈主力 ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)
题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...
- 【最小生成树】Codeforces 707B Bakery
题目链接: http://codeforces.com/problemset/problem/707/B 题目大意: 给你N个点M条无向边,其中有K个面粉站,现在一个人要在不是面粉站的点上开店,问到面 ...
随机推荐
- Scrapy+Chromium+代理+selenium
上周说到scrapy的基本入门.这周来写写其中遇到的代理和js渲染的坑. js渲染 js是爬虫中毕竟麻烦处理的一块.通常的解决办法是通过抓包,然后查看request信息,接着捕获ajax返回的消息.但 ...
- 有关Kali的方法
Kali 找回系统登陆密码的方式:https://jingyan.baidu.com/article/47a29f24560e77c0142399e3.html
- Nordic Collegiate Programming Contest 2015 D. Disastrous Downtime
You're investigating what happened when one of your computer systems recently broke down. So far you ...
- Linux学习-进程管理
为什么进程管理这么重要呢? 这是因为: 首先,我们在操作系统时的各项工作其实都是经过某个 PID 来达成的 (包括你的 bash 环境), 因此,能不能进行某项工作,就与该进程的权限有关了. 再来,如 ...
- jmeter throughput controller
工作方式:可以按规定次数执行,也可以选择按百分比执行,其中的百分比必须是10,20,30类似的整数. 使用场景:可以随机的去按百分比浏览网址. 以下是具体脚本:
- Django基于Pycharm开发之二 [使用django adminSite]
在使用django自带的adminsite的时候,有以下内容需要做. 1.数据迁移,管理表的创建. 2.启用本地化 (setting.py的配置) 一.数据迁移,默认情况下,安装django之后,dj ...
- ogre3D学习基础7---材质详解
物体着色的基础 --- 四种不同光照作用 1.环境反射 近似的模拟了场景中的全局辐射,也就是用来近似模拟所有光在场景中不断散射的结果.材质中有相应的属性来代表这种环境反射颜色. 2.漫反射 这种颜色是 ...
- python-网络编程-03
首先我们可以看下可以最简单的交互性的服务端和客户端程序 server import socket def main(): sock = socket.socket(socket.AF_INET,soc ...
- 序列化 pickle & json & shelve
把内存数据转成字符,叫序列化,dump,dumps 把字符转成内存数据类型,叫反序列化load,loads dumps:仅转成字符串 dump不仅能把对象转换成str,还能直接存到文件内 json.d ...
- xml ,html,xhtml
html,xhtml和xml的定义: 1.html即是超文本标记语言(Hyper Text Markup Language),是最早写网页的语言,但是由于时间早,规范不是很好,大小写混写且编码不规范: ...