Codeforces990F——Flow Control

传送门

开始看到的时候以为是道带权并查集,想了半天分钟实在不知道怎么维护

然后发现自己nc了

考虑到只是求一个方案而不是最优解

我们可以考虑建一颗搜索树

因为只需要满足就可以了

然后递归计算以每个点为子树的点所需要的水量

而且必然也只会有这么多的水从这个点流给子树

那就把这值赋给相连的边就可以了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
inline int read(){
    char ch=getchar();
    int res=0,f=1;
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
    return res*f;
}
const int N=200005,M=300005;
int n,m,adj[N],nxt[M<<1],to[M<<1],pos[M<<1],cnt=1;
long long tot,ans[M],a[N],val[M<<1];
bool vis[N];
inline void addedge(int u,int v,int i){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v,pos[cnt]=i;
    	nxt[++cnt]=adj[v],adj[v]=cnt,to[cnt]=u,pos[cnt]=i;
}
inline int dfs(int u,int fa){
    	vis[u]=true;
	for(int e=adj[u];e;e=nxt[e]){
    	int v=to[e];
    	if(vis[v]||v==fa)continue;
    	dfs(v,u);
    	a[u]+=a[v];
    	val[e^1]+=a[v];
    }
}
int main(){
    	n=read();
	for(int i=1;i<=n;i++)a[i]=read(),tot+=a[i];
    	m=read();
	for(int i=1;i<=m;i++){
        	int u=read(),v=read();addedge(u,v,i);
    }
	if(tot!=0){
        	cout<<"Impossible"<<'\n';
        	return 0;
    }
	else cout<<"Possible"<<'\n';
	dfs(1,0);
	for(int i=1;i<=cnt;i++){
        	if(i&1)ans[pos[i]]+=val[i];
        	else ans[pos[i]]-=val[i];
    }
	for(int i=1;i<=m;i++){
        	cout<<(ans[i])<<'\n';
    }
}

posted @ 2018-11-08 18:35  Stargazer_cykoi  阅读(153)  评论(0编辑  收藏  举报