前言:结论题似乎是我的硬伤……

题意是给你一个无向图,已知连接到每一个点的边的权值和(为整数,且属于区间[-n,n]),需要求出每条边权值的一个合法解(都要是在区间[-2*n^2,2*n^2]内的整数)。

第一个想法当然是O(n^2*m)的高斯消元。在此基础上,我想过通过选取某些节点,在边权总和中减去与之相邻的边,来逐个解出边的权值。这个本质上是优化解方程的办法难以适应全部情况,且难以通过编程实现。于是只能舍弃这个想法。

后来通过漫无边际的瞎想,观察标题,容易发现对于一棵树求解这个问题是极为容易的。于是下一个思路就是把这个无向图转化为一棵树。如下图所示,偶环的情况是很容易就能解决的。(无脑删边)

那么奇环怎么办呢?事实上,本人就卡在了这里。如果按照偶环的方法来解释奇环删边的合法性,我们发现最终有一个点的点权增加了2a。陷入僵局。这时,不妨让我们再考虑一下对树求解的过程。也就是一次dfs,对于除根结点之外的每一个结点都满足其权值和,再根据根结点是否满足其约束条件来判断是否有解。注意到上面奇环的操作,实质就意味着如果我们以一个奇环上的点为根结点,那么就可以在最后判断的时候任意加上一个偶数了。容易证明,最后与根结点相邻的边权和与其应有的边权和之差一定是一个偶数。也就是说,有奇环的图是一定有解的。因此,我们如上的处理奇环的方式,并不会影响解的存在性。

于是,我们就得到了处理环的方式:都不鸟它,并从奇环上随意拉一个点当根结点。

讲到这里,我们似乎还忽略了一个条件。

write a weight between  - 2·n2 and 2·n2 (inclusive) on each edge

当然,这个范围是相当大的,一般而言解是一定在这个区间内的(也仅限一般而言)。基于cf是一个有hack机制的网站,毫无疑问会有数据把你的解卡出这个区间(对本人而言是test 34)。因此,random_shuffle是必不可缺的

时间复杂度O(n+m)。

 #include <bits/stdc++.h>
#define int long long
#define tag(i) (ed[((i)|1)>>1].id)
using namespace std;
const int N = ;
struct edge {
int la,b;
edge(int la=,int b=):la(la),b(b) {};
} con[N<<];
int tot=,fir[N];
void add(int from,int to) {
con[++tot] = edge(fir[from],to);
fir[from] = tot;
con[++tot] = edge(fir[to],from);
fir[to] = tot;
}
int c[N],ans[N],n,m,cnt,dep[N],rt,ano,fat[N],up[N],mar[N];
typedef pair<int,int> pii;
struct data {
int a,b,id;
data(int a=,int b=,int id=):a(a),b(b),id(id){}
} ed[N];
pii ext[N];
bool vis[N];
void dfs_init(int pos,int fa) {
fat[pos] = fa;
vis[pos] = ;
dep[pos] = dep[fa] + ;
for (int i = fir[pos] ; i ; i = con[i].la) {
if (con[i].b == fa) continue;
if (vis[con[i].b]) {
if (pos > con[i].b) ext[++cnt] = pii(pos,i);
} else dfs_init(con[i].b,pos),up[con[i].b] = tag(i);
}
}
int dfs(int pos,int fa) {
vis[pos] = ;
int now = c[pos];
for (int i = fir[pos] ; i ; i = con[i].la) {
if (vis[con[i].b]) continue;
now -= (ans[tag(i)] = dfs(con[i].b,pos));
}
return now;
}
bool ocy(pii x) {
int a = x.first, b = con[x.second].b;
return (dep[a] + dep[b] + )&;
}
void print() {
puts("YES");
for (int i = ; i <= m ; ++ i) {
cout << ans[i] << endl;
}
}
void modify(int x,int y) {
int k1 = , k2 = -;
while (dep[x] > dep[y]) {
mar[up[x]] += k1;
k1 = -k1;
x = fat[x];
}
while (dep[y] > dep[x]) {
mar[up[y]] += k2;
k2 = -k2;
y = fat[y];
}
while (x != y) {
mar[up[x]] += k1;
k1 = -k1;
x = fat[x];
mar[up[y]] += k2;
k2 = -k2;
y = fat[y];
}
}
signed main() {
int a,b;
cin >> n >> m;
for (int i = ; i <= n ; ++ i) cin>>c[i];
for (int i = ; i <= m ; ++ i) {
cin >> a >> b;
ed[i] = data(a,b,i);
}
random_shuffle(ed+,ed+m+);
for (int i = ; i <= m ; ++ i) add(ed[i].a,ed[i].b);
dfs_init(,);
for (int i = ; i <= cnt ; ++ i) {
if (ocy(ext[i])) {
rt = ext[i].first, ano = con[ext[i].second].b;
modify(rt,ano);
mar[tag(ext[i].second)] ++;
break;
}
}
memset (vis,,sizeof vis);
if (rt) {
int uns = dfs(rt,)>>;
for (int i = ; i <= m ; ++ i) ans[i] += mar[i] * uns;
print();
} else {
if (dfs(,) != ) puts("NO");
else print();
}
return ;
}

小结:关于我卡在奇环无从下手,应该是缺乏与实际算法的运行相结合。

【做题】Codeforces Round #453 (Div. 1) D. Weighting a Tree——拆环的更多相关文章

  1. Codeforces Round #453 (Div. 1) D. Weighting a Tree(构造)

    题意 一个 \(n\) 个点 \(m\) 条边的无向连通图中每个点都有一个权值,现在要求给每条边定一个权值,满足每个点的权值等于所有相连的边权之和,权值可负. 题解 如果图是一棵树,那么方案就是唯一的 ...

  2. Codeforces Round #453 (Div. 1)

    Codeforces Round #453 (Div. 1) A. Hashing Trees 题目描述:给出一棵树的高度和每一层的节点数,问是否有两棵树都满足这个条件,若有,则输出这两棵树,否则输出 ...

  3. 水题 Codeforces Round #308 (Div. 2) A. Vanya and Table

    题目传送门 /* 水题:读懂题目就能做 */ #include <cstdio> #include <iostream> #include <algorithm> ...

  4. 水题 Codeforces Round #302 (Div. 2) A Set of Strings

    题目传送门 /* 题意:一个字符串分割成k段,每段开头字母不相同 水题:记录每个字母出现的次数,每一次分割把首字母的次数降为0,最后一段直接全部输出 */ #include <cstdio> ...

  5. 水题 Codeforces Round #299 (Div. 2) A. Tavas and Nafas

    题目传送门 /* 很简单的水题,晚上累了,刷刷水题开心一下:) */ #include <bits/stdc++.h> using namespace std; ][] = {" ...

  6. 水题 Codeforces Round #304 (Div. 2) A. Soldier and Bananas

    题目传送门 /* 水题:ans = (1+2+3+...+n) * k - n,开long long */ #include <cstdio> #include <algorithm ...

  7. 水题 Codeforces Round #303 (Div. 2) A. Toy Cars

    题目传送门 /* 题意:5种情况对应对应第i或j辆车翻了没 水题:其实就看对角线的上半边就可以了,vis判断,可惜WA了一次 3: if both cars turned over during th ...

  8. 水题 Codeforces Round #286 (Div. 2) A Mr. Kitayuta's Gift

    题目传送门 /* 水题:vector容器实现插入操作,暴力进行判断是否为回文串 */ #include <cstdio> #include <iostream> #includ ...

  9. 构造水题 Codeforces Round #206 (Div. 2) A. Vasya and Digital Root

    题目传送门 /* 构造水题:对于0的多个位数的NO,对于位数太大的在后面补0,在9×k的范围内的平均的原则 */ #include <cstdio> #include <algori ...

随机推荐

  1. idea上将项目上传到github

    1.下载并安装好git,然后配置git的path路径.再配置git的全局用户名和邮箱. 2.注册github账号,如果已经有github账号,则此步骤可以省略. 3.在idea中配置git,配置如下: ...

  2. Python - 5.Exception Handling

    From:http://interactivepython.org/courselib/static/pythonds/Introduction/ExceptionHandling.html Exce ...

  3. sql privot 实现行转列

    表结构如下: RefID    HRMS    Name    InsuranceMoney    InsuranceNamefb2bdee8-e4c9-4470-8e7f-14550d3212f7  ...

  4. Spark学习之路 (九)SparkCore的调优之数据倾斜调优

    摘抄自:https://tech.meituan.com/spark-tuning-pro.html 数据倾斜调优 调优概述 有的时候,我们可能会遇到大数据计算中一个最棘手的问题——数据倾斜,此时Sp ...

  5. 【Linux学习九】负载均衡

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 一.高并发 随着应用访问量的增加,带来高并发处理问题. 具体有两个: ...

  6. redis 性能建议

    因为 RDB 文件只用作后备用途,建议只在 Slave 上持久化 RDB 文件,而且只要15分钟一次就够了,只保留 save 900 1 这条规则. 如果 Enable AOF,好处是在恶劣请看下也只 ...

  7. 转:控制ComboBox下拉框的下拉部分宽度,使内容能够显示完全

    一般的情况下,如果下拉框的选项的文字太长,下拉框ComboBox的Width宽度属性我们又不想要改变(默认不变),下拉选项的文字内容就会被截剪,如下图所示: 解决办法: 1.自动判断下拉选项的文字长度 ...

  8. XWIKI部署安装

    http://www.linuxidc.com/Linux/2016-08/134408.htm

  9. navicat 连接postgresql报错pg_hba.conf

    PostgreSQ数据库为了安全,它不会监听除本地以外的所有连接请求,当用户通过JDBC访问是,会报一些如下的异常: org.postgresql.util.PSQLException: FATAL: ...

  10. 文件缓冲区在fork后复制

    场景:父进程trace进程A,当A进程fork子进程B时,让父进程也fork子进程去trace子进程B,用于trace的进程将被trace的进程发生的系统调用号通过fprintf存入各自文件中 问题: ...