正常解法要高斯消元,由于数据范围太大,考虑换个思路
每条边是一个未知数,每个点是一个方程,各联通块之间不影响,所以每个联通块单独考虑那么可知
当n< m时,未知数比方程多,一定多解或无解
当n> m-1时,图一定不连通的,所以不会有这种情况
于是m-1<=n<=m,就可以树形DP辣
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 110000;
const int maxm = 510000;
struct edge
{
int y,nex;
edge(){}
edge(int _y,int _nex){y=_y;nex=_nex;}
}a[maxm<<1]; int len,fir[maxn];
ll ve[maxm<<1],ans[maxm],v[maxn];
int n,m,e[maxm][2];
void ins(int x,int y){ a[++len]=edge(y,fir[x]); fir[x]=len; }
int fa[maxn];
int find_(int x)
{
if(fa[x]==x) return x;
return fa[x]=find_(fa[x]);
}
bool vis[maxn];
int bel[maxn];
int cnt,tot[maxn],etot[maxn];
int t[maxn],tp,cir[maxn],cn,cid[maxn];
bool ev[maxn];
bool f_cir(int x,int fr)
{
if(ev[x])
{
int la=0;
while(la!=x)
{
la=t[tp--];
cir[++cn]=la;
cid[la]=cn;
}
return true;
}
ev[x]=true;
t[++tp]=x;
for(int k=fir[x];k;k=a[k].nex)
if(a[k].y!=fr)
if(f_cir(a[k].y,x))return true;
tp--;
return false;
}
void sear(int x,int fr,int pre)
{
for(int k=fir[x];k;k=a[k].nex)
{
int y=a[k].y;
if(y!=fr&&!cid[y]) sear(y,x,k);
v[x]-=ve[k]>>1;
}
if(pre) ve[pre]=ve[pre^1]=v[x]<<1,v[x]=0;
}
int main()
{
len=1; memset(fir,0,sizeof fir);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%lld",&v[i]),fa[i]=i;
for(int i=1;i<=m;i++)
{
int x,y; scanf("%d%d",&x,&y);
fa[find_(y)]=find_(x);
ins(x,y); ins(y,x);
e[i][0]=x; e[i][1]=y;
}
cnt=0;
for(int i=1;i<=n;i++)
{
int f1=find_(i);
if(!bel[f1])
{
bel[i]=bel[f1]=++cnt;
tot[cnt]=1;
}
else bel[i]=bel[f1],tot[bel[i]]++;
}
for(int i=1;i<=m;i++)
etot[bel[e[i][0]]]++;
memset(vis,false,sizeof vis);
memset(ev,false,sizeof ev);
for(int l=1;l<=n;l++)
{
int f1=find_(l);
if(vis[f1]) continue;
vis[f1]=true;
f1=bel[f1];
if(tot[f1]<etot[f1]) { printf("0\n"); return 0; }
if(tot[f1]==etot[f1])
{
tp=cn=0;
f_cir(l,0);
if(cn%2==0) { printf("0\n"); return 0; }
for(int j=1;j<=cn;j++)
sear(cir[j],0,0);
ll xc=0,sc=0;
for(int i=1;i<=cn;i++) xc+=v[cir[i]];
for(int i=2;i<cn;i+=2)
sc+=v[cir[i]];
sc=xc-sc*2;
if(sc%2==1) { printf("0\n"); return 0; }
for(int i=1,la=cir[cn];i<=cn;la=cir[i],i++)
{
for(int k=fir[cir[i]];k;k=a[k].nex)
if(a[k].y==la)
{
ve[k]=ve[k^1]=sc;
sc=2*(v[cir[i]]-sc/2);
break;
}
}
}
else
{
sear(l,0,0);
if(v[l]) { printf("0\n"); return 0; }
}
}
for(int i=2;i<=len;i+=2) ans[i>>1]=ve[i];
for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
return 0;
}