传送门
文章目录
- 题意:
- 思路:
题意:
给你一颗nnn个点的图,每个点都有一个点权cic_ici,要求你给每个边赋一个权值kik_iki,要求对于每个点与他相连的边的权值之和等于这个点的点权cic_ici。
n≤1e5,n−1≤m≤1e5,−n≤ci≤nn\le1e5,n-1\le m\le 1e5,-n\le c_i\le nn≤1e5,n−1≤m≤1e5,−n≤ci≤n
思路:
考虑这个图是一棵树的时候,那么我们从叶子开始向上递推一定能推出来每条边的唯一解,检查一下根节点是否合法即可。
考虑一般图的情况,我们还是先dfsdfsdfs找出来一棵树,让后如果此时根节点已经合法,那么显然将其他非树边都置为000即可。如果不合法,我们考虑如何操作能使其合法。
想想还有什么条件没有用到,他是个图,我们只拿出来了一棵树,不合法的时候只能通过环来平衡一下。考虑两个点u,vu,vu,v,他们之间有一条边构成环,假设我们将这个边权值置为xxx,这两个点在原树中连向父亲的边边权为y,zy,zy,z,加上这个边构成环之后边权变成了y−x,z−xy-x,z-xy−x,z−x,继续向上递推手玩一下不难发现是正负交替的,所以我们分奇偶环来考虑。
(1)(1)(1)考虑偶环的时候,设u,vu,vu,v的lcalcalca为fff,由于其是奇环,那么两个点到fff的距离的奇偶性不同,所以他们最终的符号是相反的,也就是在fff处,两个分别是+x,−x+x,-x+x,−x,所以就抵消了,并无贡献。
(2)(2)(2)考虑奇环的时候,跟上面一样的分析方法,可以发现他们最终的状态是相同的,也是2x2x2x,再向上也是2x2x2x的变化量,所以这个是可以用来修改根节点权值的。
所以通过以上分析,根节点如果是奇数一定无解,否则就找个奇环来构造一下即可。
最后,离天下大谱之我一发过了。
// Problem: D. Weighting a Tree
// Contest: Codeforces - Codeforces Round #453 (Div. 1)
// URL: https://codeforces.com/problemset/problem/901/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops,fast-math")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4.1,sse4.2,avx,avx2,popcnt,tune=native")
//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;int n,m;
vector<PII>v[N];
LL c[N],ans[N];
int fa[N],depth[N],ff[N];
bool st[N],flag=false;void dfs1(int u) {st[u]=1;for(auto x:v[u]) {if(st[x.X]) continue;depth[x.X]=depth[u]+1;ff[x.X]=u;dfs1(x.X);c[u]-=c[x.X];ans[x.Y]=c[x.X];fa[x.X]=x.Y;}
}void solve(int u,int v,int id) {int op=depth[u]&1;if(!op) {ans[id]=c[1]/2;int op=-1;while(u) {ans[fa[u]]+=op*c[1]/2;u=ff[u];op*=-1;}op=-1;while(v) {ans[fa[v]]+=op*c[1]/2;v=ff[v];op*=-1;}} else {ans[id]=-c[1]/2;int op=1;while(u) {ans[fa[u]]+=op*c[1]/2;u=ff[u];op*=-1;}op=1;while(v) {ans[fa[v]]+=op*c[1]/2;v=ff[v];op*=-1;}}
}void dfs2(int u,int fa) {if(flag) return;st[u]=1;for(auto x:v[u]) {if(flag) return;if(x.X==fa) continue;if(st[x.X]) {if((depth[u]+depth[x.X])%2==0) {flag=true;solve(u,x.X,x.Y);return;}continue;}dfs2(x.X,u);}
}int main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);scanf("%d%d",&n,&m);for(int i=1;i<=n;i++) scanf("%lld",&c[i]);for(int i=1;i<=m;i++) {int a,b; scanf("%d%d",&a,&b);v[a].pb({b,i}); v[b].pb({a,i});}dfs1(1);if(c[1]==0) {puts("YES");for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);puts("");return 0;} else if(abs(c[1])&1) {puts("NO");return 0;}memset(st,0,sizeof(st));dfs2(1,0);if(flag) {puts("YES");for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);puts("");} else {puts("NO");}return 0;
}
/**/