Solution

前言:相比于前向星,我更喜欢vector,码量更小。
根据题目意思,构建一个无向图,无向图的花费部分需要记录两个变量,一个是自己的x,一个是终点的y。这里要记得换起点要换x和y。
那么这里把深度优先搜索遍历全部节点,把从未遍历过的节点定义成1.0,其余节点去根据x,y去确定第一次来到的点的值,如果第二次遍历到这个点,就要去判断向前的值是否满足当前的终点,如果不满足flag=true。

#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
typedef long long ll;

inline int read() {
    int s = 0, w = 1; char ch = getchar();
    while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); }
    while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
    return s * w;
}

const int N = 1e4 + 7;
const double eps = 1e-3;
struct Node {
    int v;
    int wx, wy;
};
vector<Node> e[N];
bool vis[N], flag;
double w[N];
int n, m;

void dfs(int u, int fa) {
    vis[u] = 1;
    for (auto it : e[u]) {
        if (it.v != fa) {
            if (vis[it.v]) {
                if (abs(w[it.v] - w[u] * it.wy / it.wx) <= eps)
                    continue;
                else {
                    flag = true;
                    return;
                }
            }
            else {
                w[it.v] = w[u] * it.wy / it.wx;
                dfs(it.v, u);
            }
        }
    }
}

int main() {
    int T = read();
    for (int ca = 1; ca <= T; ++ca) {
        flag = false;
        n = read(), m = read();
        memset(vis, 0, sizeof(vis));
        for (int i = 0; i <= n; ++i) e[i].clear();
        for (int i = 1; i <= m; ++i) {
            int u = read(), v = read(), x = read(), y = read();
            e[u].push_back({ v,x,y });
            e[v].push_back({ u,y,x }); //注意更换x,y
        }
        for (int i = 1; i <= n; ++i) {
            if (!vis[i]) {
                w[i] = 1.0;
                dfs(i, 0);
            }
            if (flag)   break;
        }
        if (flag)
            printf("Case #%d: No\n", ca);
        else
            printf("Case #%d: Yes\n", ca);
    }
    return 0;
}