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个面粉站,现在一个人要在不是面粉站的点上开店,问到面 ...
随机推荐
- Docker DockerFile文件指令 & 构建
1.dockerfile指令格式 # Comment注释 INSTRUCTION argument指令名 + 参数 2.普通指令 1. FROM 已存在的镜像,基础镜像,第一条非注释指令 FROM & ...
- Vim如何显示和关闭行号
显示行号: set nu 去除行号: set nonu
- CentOS7 安装操作命令
#timedatectl set-timezone Asia/Shanghai 关闭SELinux vi /etc/sysconfig/selinux #SELINUX=enforcing SELIN ...
- 【php】命名空间的影响
命名空间对代码的影响 类(包含抽象类和traits) 接口 常量 函数
- manjaro kde netease-cloud-music 网易云音乐
- python3 简单服务器监控,自动发送邮件
import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartimpo ...
- zoj 4056
At 0 second, the LED light is initially off. After BaoBao presses the button 2 times, the LED light ...
- 利用http录制jmeter脚本
1.在WorkBench下新建HTTP(S) Test Script Recorder,默认端口号为8080,假如8080被占用,则使用其他端口号:且为了使录制保存到线程组里,也同时新建一个线程组Tr ...
- #ifndef、#def、#endif说明
你所遇到的这几个宏是为了进行条件编译.一般情况下,源程序中所有的行都参加编译.但是有时希望对其中一部分内容只在满足一定条件才进行编译,也就是对一 部分内容指定编译的条件,这就是“条件编译”.有时,希望 ...
- [转] babel-present-env 与 babel-polyfill 学习总结
babelrc 配置文件 { "presets": [ [ "env", { "modules": false, "useBuil ...