JZOJ-senior-5916. 【NOIP2018模擬10.20】flow
Time Limits: 1000 ms Memory Limits: 262144 KB
Description
你是申國的一個地方長官,你手下有n個城市。
為了加強基礎設施建設,在2020全面建成小康社會,統籌推進經濟建設、政治建設、文化建設、社會建設、生態文明建設,堅定實施科教興國戰略、人才強國戰略、創新驅動發展戰略、鄉村振興戰略、區域協調發展戰略、可持續發展戰略、軍民融合發展戰略,突出抓重點、補短板、強弱項,特別是要堅決打好防範化解重大風險、精準脫貧、汙染防治的攻堅戰,使全面建成小康社會得到人民認可、經得起歷史檢驗。你認為本省的水利調配非常有問題,這導致部分地區出現嚴重的缺水,而部分地區卻全年洪災氾濫。
於是你打算將原有的但是已經廢棄了的m條水管重新使用。第i條水管連線城市xi和yi。這些水管聯通了所有城市。每座城市對水的需求不同設為ai,部分城市處於缺水狀態,ai為正,缺水量剛好為ai mol。部分城市因為有水庫,ai為負,它需要向外輸送-ai mol的水才能不形成洪災。對於每條水管,你需要決定它的輸送量fi,若fi為正則表示從xi向yi輸送fi mol的水,fi為負則表示從yi向xi輸送-fi mol的水。
你需要做到每個城市都剛好滿足它的需求,即缺ai mol水的城市需要剛好輸入ai的水,而多出-ai mol水的城市需要剛好輸出-ai mol水。
你需要判斷能否滿足要求,若滿足,你還需要輸出所有的f。
Input
第一行一個整數n。 第二行n個整數ai。 第三行一個整數m。 接下來m行每行兩個整數,xi,yi。 意義如題中所述。
Output
如果不能滿足要求,輸出”Impossible”。 否則第一行輸出”Possible”,接下來m行,第i+1行輸出fi。 若有多組解,隨意輸出一組即可。
Sample Input
4 3 -10 6 1 5 1 2 3 2 2 4 3 4 3 1
Sample Output
Possible 4 -6 8 -7 7
Data Constraint
對於10%:n<=5,|ai|<=20 對於20%:n<=10,|ai|<=20 對於另30%:n<=1000,m=n,|ai|<=20 對於100%:n<=200000,m<=300000,你使用longint(pascal)/int(c++)就能夠儲存ai。 資料純隨機。
Hint
Tips mol是一種單位。
Solution
顯然僅 的和為 時有解 我們發現,在有解的情況下,只要這些水管將所有的城市連通了就一定就可以保證有方案滿足題意,於是我們搞出一棵生成樹,對於 ,連線 和它父親節點的邊權就是 的子樹和,注意判斷一下方向來確定正負
Code
#include<algorithm>
#include<cstdio>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
#define ll long long
using namespace std;
const int N=3e5+5;
int n,m,num;
int b[N],f[N],v[N],sz[N],last[N];
ll s,g[N],ans[N];
struct node
{
int x,y;
}a[N];
struct edge
{
int to,next,id,k;
}e[2*N];
int get(int x)
{
return f[x]=f[x]==x?x:get(f[x]);
}
void merge(int x,int y)
{
f[get(x)]=get(y);
}
void link(int x,int y,int z,int w)
{
e[++num]=(edge){y,last[x],z,w},last[x]=num;
}
void dfs(int x)
{
v[x]=1;
for(int w=last[x];w;w=e[w].next)
{
int y=e[w].to;
if(v[y]) continue;
dfs(y);
g[x]+=g[y];
int id=e[w].id;
ans[id]=e[w].k*g[y];
}
}
int main()
{
freopen("flow.in","r",stdin);
freopen("flow.out","w",stdout);
scanf("%d",&n);
fo(i,1,n)
{
scanf("%d",&b[i]),s+=b[i];
f[i]=i,sz[i]=1,g[i]=b[i];
}
if(s)
{
printf("Impossible\n");
return 0;
}
else printf("Possible\n");
scanf("%d",&m);
fo(i,1,m)
{
scanf("%d%d",&a[i].x,&a[i].y);
if(get(a[i].x)!=get(a[i].y))
{
merge(a[i].x,a[i].y);
link(a[i].x,a[i].y,i,1);
link(a[i].y,a[i].x,i,-1);
}
}
dfs(1);
fo(i,1,m) printf("%lld\n",ans[i]);
}