Question
给你个点条边,点之间相互连通。每个点的值等于其所连的边的值的一半的和,告诉你每个点的值。
对于边的值:如果有唯一解,则输出唯一解,否则输出。
Solution
对于这道题,我们来看一看与的关系。
我们可以发现,这是一棵树,且有些节点只连了一条边,很容易求出边权,并将其所连的点进行更改即可删掉此边,不断如此即可。
线性方程组的方程数小于变量数,不可能有唯一解。
我们发现会有一个环。
对于这个环以外的值,我们像那样做,最后只剩下一个环。
如果这个环有偶数个点的话,没有唯一解,输出。(鄙人太弱,不会证明)
如果有奇数个点的话,一定有唯一解。
对于奇数个点(设有个点),我们可以将其列出个方程,
自己想一想,解一解即可。
Code
#include<cstdio>
#include<cstring>
#define N 100010
#define ll long long
using namespace std;
struct node{int v,fr,sg;}e[N<<1];
int n,m,tail[N],hav[N],rem[N],edge[N],cnt=0;
int f[N],l=0,r=0,las,ha=0;
ll c[N],aw[N],s=0,ss=0;
bool bz[N],bz1[N];
inline int read()
{
int x=0,f=0; char c=getchar();
while (c<'0' || c>'9') f=(c=='-') ? 1:f,c=getchar();
while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return f ? -x:x;
}
inline void add(int u,int v,int sg) {e[++cnt]=(node){v,tail[u],sg}; tail[u]=cnt;}
int main()
{
freopen("tube.in","r",stdin);
freopen("tube.out","w",stdout);
n=read(),m=read();
if (m>n) {puts("0"); return 0;}
for (int i=1;i<=n;i++) c[i]=read();
for (int i=1,u,v;i<=m;i++)
{
u=read(),v=read();
add(u,v,i),add(v,u,i);
hav[u]++,hav[v]++;
}
for (int i=1;i<=n;i++)
if (hav[i]==1) f[++r]=i;
while (l++<r)
{
for (int p=tail[f[l]],v,sg;p;p=e[p].fr)
{
sg=e[p].sg;
if (!bz[sg]) aw[sg]=c[f[l]]<<1,bz[sg]=1;
v=e[p].v,hav[v]--,c[v]-=c[f[l]];
if (hav[v]==1) f[++r]=v;
}
}
if (m==n-1) {for (int i=1;i<=m;i++) printf("%lld
",aw[i]); return 0;}
// int haia=0;
// for (int i=1;i<=n;i++)
// if (hav[i]>1) haia++,printf("%d ",i);
// printf("%d
",haia);
for (int i=1;i<=n;i++)
if (hav[i]>1) {rem[2]=i,ha=1; break;}
for (int p=tail[rem[2]],v;p;p=e[p].fr)
{
v=e[p].v;
if (hav[v]>1)
{
if (ha==1) rem[1]=v,edge[2]=e[p].sg,ha=3;
else {rem[3]=v,edge[3]=e[p].sg; break;}
}
}
l=1;memset(bz1,0,sizeof(bz1));
bz1[rem[1]]=bz1[rem[2]]=bz1[rem[3]]=1;
while (l++<ha)
{
for (int p=tail[rem[l]],v;p;p=e[p].fr)
{
v=e[p].v;
if (hav[v]==1 || bz1[v]) continue;
rem[++ha]=v,edge[ha]=e[p].sg,bz1[v]=1;
}
}
for (int p=tail[rem[ha]];p;p=e[p].fr)
if (e[p].v==rem[1]) edge[1]=e[p].sg;
if (!(ha & 1)) {puts("0"); return 0;}
for (int i=1;i<=ha;i++) ss+=c[rem[i]];
for (int i=1;i<ha;i+=2) s+=c[rem[i]];
aw[edge[ha]]=ss-(s<<1);
for (int i=ha-1;i>0;i--)
aw[edge[i]]=(c[rem[i]]<<1)-aw[edge[i+1]];
for (int i=1;i<=m;i++)
printf("%lld
",aw[i]);
return 0;
}