官方题解:http://boi2013.informatik-olympiade.de/wp-content/uploads/2013/05/pipes-spoiler.pdf
输入构成一个n个m元方程组 当m<=n是有唯一解,而m>=n-1
所以只需考虑 m==n-1 m==n
m==n-1
这是一棵树 从叶子往上推就好了 在根节点判一下是否矛盾
m==n
这是一个环套树 先处理到只剩一个环
然后如果环是奇数 可以解方程
如果是偶数 就有无数解
#include<cstdio> #include<cstdlib> #include<algorithm> #define V G[p].v using namespace std; typedef long long ll; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; } return *p1++; } inline void read(int &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } inline void read(ll &x){ char c=nc(),b=1; for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1; for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b; } struct edge{ int u,v; int idx; int next; }; edge G[1000005]; int head[100005],inum; inline void add(int u,int v,int idx,int p){ G[p].u=u; G[p].v=v; G[p].idx=idx; G[p].next=head[u]; head[u]=p; } int n,m; ll s[100005],w[100005]; int deg[100005]; namespace Work1{ inline ll dfs(int u,int fa){ ll sum=0; for (int p=head[u];p;p=G[p].next) if (V!=fa) sum+=(w[G[p].idx]=dfs(V,u)); return s[u]-sum; } inline void Solve(){ if (dfs(1,0)) printf("0\n"); else { for (int i=1;i<=m;i++) printf("%lld\n",2*w[i]); } } } namespace Work2{ int Q[100005],l,r; int cnt; int a[100005],e[100005]; int del[100005]; inline void Solve(){ l=r=-1; for (int i=1;i<=n;i++) if (deg[i]==1) Q[++r]=i; while (l<r) { int u=Q[++l]; del[u]=1; for (int p=head[u];p;p=G[p].next) if (!del[V]) { w[G[p].idx]=s[u]; s[V]-=s[u]; deg[V]--; if (deg[V]==1) Q[++r]=V; } } for (int i=1,flag=0;i<=n && !flag;i++) if (!del[i]) a[++cnt]=i,flag=1; while (1) { int u=a[cnt]; del[u]=1; int flag=0; for (int p=head[u];p && !flag;p=G[p].next) if (!del[V]) a[++cnt]=V,e[cnt-1]=G[p].idx,flag=1; if (!flag) break; } for (int p=head[a[cnt]],flag=0;p && !flag;p=G[p].next) if (V==a[1]) e[cnt]=G[p].idx,flag=1; if (cnt&1) { ll itmp=0; for (int i=1,t=1;i<=cnt;i++,t=-t) itmp+=s[a[i]]*t; w[e[cnt]]=itmp/2; for (int i=cnt-1;i>=1;i--) w[e[i]]=s[a[i+1]]-w[e[i+1]]; for (int i=1;i<=m;i++) printf("%lld\n",2*w[i]); } else printf("0\n"); } } int main() { int iu,iv; freopen("t.in","r",stdin); freopen("t.out","w",stdout); read(n); read(m); if (m>n) return printf("0\n"),0; for (int i=1;i<=n;i++) read(s[i]); for (int i=1;i<=m;i++) read(iu),read(iv),add(iu,iv,i,++inum),add(iv,iu,i,++inum),deg[iu]++,deg[iv]++; if (m==n-1) Work1::Solve(); else if (m==n) Work2::Solve(); return 0; }