Codeforces Round #453 (Div. 1) D. Weighting a Tree 构造 + dfs树
傳送門
文章目錄
- 題意:
- 思路:
題意:
給你一顆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; } /**/總結
以上是生活随笔為你收集整理的Codeforces Round #453 (Div. 1) D. Weighting a Tree 构造 + dfs树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 木瓜葛根粉真的丰胸吗
- 下一篇: 夏天出汗有助于减肥吗