爆搜+取对数优化
很显然我们可以定一个点,然后DFS下去看有没有矛盾。但是这样会炸精度。于是考虑判断a*b==a*c可以转为判断log(a*b)==log(a*c)也就是log(a)+log(b)==log(a)+log(c)。这样精度就安全了。
#include<cstdio>
#include<cmath>
#include<cstring>
#define N 1005
#define M 10005
using namespace std;
struct edge{int next,to;double v;bool cir;}e[M<<1];
const double eps = 1e-8;
double f[N];
int last[N], ecnt;
bool flag, vis[N], cir[N];
void add(int a, int b, double v, bool c)
{
e[++ecnt]=(edge){last[a],b,v,c};
last[a]=ecnt;
}
void clear()
{
ecnt=0;
memset(last,0,sizeof(last));
memset(vis,0,sizeof(vis));
}
void dfs(int x, double sum, bool c)
{
vis[x]=1; f[x]=sum; cir[x]=c;
for(int i = last[x]; i; i=e[i].next)
{
int y=e[i].to;
if(vis[y])
{
if(cir[y]!=(c^e[i].cir) || abs(sum+e[i].v-f[y])>eps)
{
flag=0;
return;
}
}
else
{
dfs(y,sum+e[i].v,c^e[i].cir);
if(!flag)return;
}
}
}
int main()
{
int T;
scanf("%d",&T);
for(int t = 1; t <= T; t++)
{
clear();
int n, m;
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i++)
{
int u, v; double x, y;
scanf("%d%d%lf%lf",&u,&v,&x,&y);
add(u,v,log(abs(y/x)),y<0);
add(v,u,log(abs(x/y)),y<0);
}
flag=1;
for(int i = 1; i <= n && flag; i++)
if(!vis[i])
dfs(i,0,0);
if(flag)printf("Case #%d: Yes\n",t);
else printf("Case #%d: No\n",t);
}
}