生活随笔
收集整理的這篇文章主要介紹了
中石油训练赛 - Flow Finder(树上模拟)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題目鏈接:點(diǎn)擊查看
題目大意:給出一棵樹(shù),模擬網(wǎng)絡(luò)流的過(guò)程,每個(gè)節(jié)點(diǎn)代表的是通過(guò)該節(jié)點(diǎn)的流量,虛擬源點(diǎn)連向每個(gè)葉子節(jié)點(diǎn),根節(jié)點(diǎn)作為超級(jí)匯點(diǎn),每條邊的流向是流向其父節(jié)點(diǎn),有一些節(jié)點(diǎn)的流量沒(méi)有給出,現(xiàn)在問(wèn)是否存在著唯一的一種賦值方案,使得每個(gè)節(jié)點(diǎn)的賦值合法且唯一
題目分析:因?yàn)樵袋c(diǎn)與葉子節(jié)點(diǎn)相連,所以我們的當(dāng)務(wù)之急是需要將所有的葉子節(jié)點(diǎn)進(jìn)行合法的賦值,然后 dfs 自底向上檢查一下每個(gè)節(jié)點(diǎn)是否合法且唯一即可,那么我們?cè)撊绾谓o葉子節(jié)點(diǎn)賦值呢
因?yàn)檎脴?shù)的每個(gè)節(jié)點(diǎn)都是一個(gè)互相限制的過(guò)程,同理葉子節(jié)點(diǎn)也會(huì)被其祖先節(jié)點(diǎn)的流量所限制,所以我們?cè)诮o葉子節(jié)點(diǎn)賦值時(shí),并不關(guān)心那些流量未知的節(jié)點(diǎn),對(duì)于每個(gè)葉子結(jié)點(diǎn) i 只需要記錄一下 fa[ i ] 代表的是 i 的第一個(gè)已經(jīng)有確定流量的祖先節(jié)點(diǎn),根據(jù)這個(gè)祖先的流量來(lái)判斷能否給當(dāng)前葉子節(jié)點(diǎn)賦值即可
代碼: ?
#pragma GCC optimize(2)
#pragma GCC optimize("Ofast","inline","-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=3e5+100;vector<int>node1[N],node2[N];int fa[N];LL val[N],sub[N];//sub數(shù)組用來(lái)實(shí)時(shí)每個(gè)點(diǎn)的流量void dfs1(int u)
{for(auto v:node1[u]){if(val[u])fa[v]=u;elsefa[v]=fa[u];dfs1(v);}
}void dfs2(int u)
{LL temp=val[u];if(node1[u].size())val[u]=0;for(auto v:node1[u]){dfs2(v);val[u]+=val[v];}if(val[u]==0||temp>0&&val[u]!=temp){puts("impossible");exit(0);}
}int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);int n;scanf("%d",&n);for(int i=2;i<=n;i++){int fa;scanf("%d",&fa);node1[fa].push_back(i);}for(int i=1;i<=n;i++){scanf("%lld",val+i);sub[i]=val[i];}dfs1(1);for(int i=1;i<=n;i++){sub[fa[i]]-=val[i];//更新一下每個(gè)節(jié)點(diǎn)的流量if(node1[i].empty()&&!val[i])//未賦值的葉子結(jié)點(diǎn) node2[fa[i]].push_back(i);}for(int i=1;i<=n;i++)if(node2[i].size())//有流量的節(jié)點(diǎn) {if(node2[i].size()==1)//如果只有一個(gè)葉子節(jié)點(diǎn),那么賦值為sub[i]val[node2[i].front()]=sub[i];else if(node2[i].size()==sub[i])//如果有sub[i]個(gè)葉子結(jié)點(diǎn),每個(gè)節(jié)點(diǎn)賦值為1{for(auto v:node2[i])val[v]=1;}}dfs2(1);//自底向上檢查for(int i=1;i<=n;i++)printf("%lld\n",val[i]);return 0;
}
?
總結(jié)
以上是生活随笔 為你收集整理的中石油训练赛 - Flow Finder(树上模拟) 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。