結果

問題 No.1502 Many Simple Additions
ユーザー tokusakuraitokusakurai
提出日時 2021-05-07 23:15:08
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 156 ms / 2,000 ms
コード長 6,197 bytes
コンパイル時間 2,578 ms
コンパイル使用メモリ 219,992 KB
実行使用メモリ 29,992 KB
最終ジャッジ日時 2023-10-13 22:37:01
合計ジャッジ時間 5,457 ms
ジャッジサーバーID
(参考情報)
judge13 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
4,348 KB
testcase_01 AC 2 ms
4,352 KB
testcase_02 AC 1 ms
4,348 KB
testcase_03 AC 2 ms
4,348 KB
testcase_04 AC 2 ms
4,352 KB
testcase_05 AC 2 ms
4,352 KB
testcase_06 AC 2 ms
4,352 KB
testcase_07 AC 2 ms
4,352 KB
testcase_08 AC 1 ms
4,348 KB
testcase_09 AC 1 ms
4,352 KB
testcase_10 AC 2 ms
4,352 KB
testcase_11 AC 1 ms
4,348 KB
testcase_12 AC 1 ms
4,352 KB
testcase_13 AC 2 ms
4,348 KB
testcase_14 AC 2 ms
4,352 KB
testcase_15 AC 2 ms
4,348 KB
testcase_16 AC 2 ms
4,352 KB
testcase_17 AC 2 ms
4,352 KB
testcase_18 AC 1 ms
4,352 KB
testcase_19 AC 1 ms
4,352 KB
testcase_20 AC 2 ms
4,352 KB
testcase_21 AC 2 ms
4,348 KB
testcase_22 AC 2 ms
4,348 KB
testcase_23 AC 1 ms
4,348 KB
testcase_24 AC 1 ms
4,352 KB
testcase_25 AC 2 ms
4,348 KB
testcase_26 AC 1 ms
4,348 KB
testcase_27 AC 63 ms
24,584 KB
testcase_28 AC 64 ms
24,924 KB
testcase_29 AC 24 ms
18,948 KB
testcase_30 AC 151 ms
29,908 KB
testcase_31 AC 146 ms
29,992 KB
testcase_32 AC 156 ms
29,916 KB
testcase_33 AC 78 ms
17,828 KB
testcase_34 AC 83 ms
18,812 KB
testcase_35 AC 80 ms
18,108 KB
testcase_36 AC 34 ms
8,868 KB
testcase_37 AC 34 ms
8,780 KB
testcase_38 AC 43 ms
12,432 KB
testcase_39 AC 25 ms
7,952 KB
testcase_40 AC 19 ms
11,528 KB
testcase_41 AC 7 ms
7,784 KB
testcase_42 AC 63 ms
22,584 KB
testcase_43 AC 1 ms
4,348 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
#define rep(i, n) for(int i = 0; i < n; i++)
#define rep2(i, x, n) for(int i = x; i <= n; i++)
#define rep3(i, x, n) for(int i = x; i >= n; i--)
#define each(e, v) for(auto &e: v)
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sz(x) (int)x.size()
using ll = long long;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
const int MOD = 1000000007;
//const int MOD = 998244353;
const int inf = (1<<30)-1;
const ll INF = (1LL<<60)-1;
template<typename T> bool chmax(T &x, const T &y) {return (x < y)? (x = y, true) : false;};
template<typename T> bool chmin(T &x, const T &y) {return (x > y)? (x = y, true) : false;};

struct io_setup{
    io_setup(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);
        cout << fixed << setprecision(15);
    }
} io_setup;

template<int mod>
struct Mod_Int{
    int x;

    Mod_Int() : x(0) {}

    Mod_Int(long long y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

    Mod_Int &operator += (const Mod_Int &p){
        if((x += p.x) >= mod) x -= mod;
        return *this;
    }

    Mod_Int &operator -= (const Mod_Int &p){
        if((x += mod - p.x) >= mod) x -= mod;
        return *this;
    }

    Mod_Int &operator *= (const Mod_Int &p){
        x = (int) (1LL * x * p.x % mod);
        return *this;
    }

    Mod_Int &operator /= (const Mod_Int &p){
        *this *= p.inverse();
        return *this;
    }

    Mod_Int &operator ++ () {return *this += Mod_Int(1);}

    Mod_Int operator ++ (int){
        Mod_Int tmp = *this;
        ++*this;
        return tmp;
    }

    Mod_Int &operator -- () {return *this -= Mod_Int(1);}

    Mod_Int operator -- (int){
        Mod_Int tmp = *this;
        --*this;
        return tmp;
    }

    Mod_Int operator - () const {return Mod_Int(-x);}

    Mod_Int operator + (const Mod_Int &p) const {return Mod_Int(*this) += p;}

    Mod_Int operator - (const Mod_Int &p) const {return Mod_Int(*this) -= p;}

    Mod_Int operator * (const Mod_Int &p) const {return Mod_Int(*this) *= p;}

    Mod_Int operator / (const Mod_Int &p) const {return Mod_Int(*this) /= p;}

    bool operator == (const Mod_Int &p) const {return x == p.x;}

    bool operator != (const Mod_Int &p) const {return x != p.x;}

    Mod_Int inverse() const{
        assert(*this != Mod_Int(0));
        return pow(mod-2);
    }

    Mod_Int pow(long long k) const{
        Mod_Int now = *this, ret = 1;
        for(; k > 0; k >>= 1, now *= now){
            if(k&1) ret *= now;
        }
        return ret;
    }

    friend ostream &operator << (ostream &os, const Mod_Int &p){
        return os << p.x;
    }

    friend istream &operator >> (istream &is, Mod_Int &p){
        long long a;
        is >> a;
        p = Mod_Int<mod>(a);
        return is;
    }
};

using mint = Mod_Int<MOD>;

ll K;

template<typename T, bool directed = false>
struct Weighted_Graph{
    struct edge{
        int to; T cost; int id;
        edge(int to, T cost, int id) : to(to), cost(cost), id(id) {}
    };

    vector<vector<edge>> es;
    const T INF_T;
    const int n;
    int m;

    vector<vector<T>> a;
    vector<vector<bool>> used;
    vector<T> mi, ma;
    T tmp;

    Weighted_Graph(int n) : es(n), INF_T(numeric_limits<T>::max()/2), n(n), m(0), a(n, vector<T>(2, -INF_T)), used(n, vector<bool>(2, false)) {}

    void add_edge(int from, int to, T cost){
        es[from].emplace_back(to, cost, m);
        if(!directed) es[to].emplace_back(from, cost, m);
        m++;
    }

    void dfs(int now, int col, T x){
        a[now][col] = x;
        used[now][col] = true;
        chmin(mi[col], x), chmax(ma[col], x);
        col ^= 1;

        if(used[now][0] && used[now][1]){
            T y = a[now][1]-a[now][0];
            if(y < 0 || (y&1) || (tmp != -INF_T && tmp != y/2)){
                cout << "0\n";
                exit(0);
            }
            tmp = y/2;
        }

        each(e, es[now]){
            if(used[e.to][col]){
                if(a[e.to][col] != e.cost-x){
                    cout << "0\n";
                    exit(0);
                }
            }
            else{
                dfs(e.to, col, e.cost-x);
            }
        }
    }

    vector<mint> ans1, ans2; //各連結成分ごとにmaxがKになるもの、全体の場合の数

    void solve(){
        mi.resize(2), ma.resize(2);
        rep(i, n){
            if(used[i][0] || used[i][1]) continue;

            fill(all(mi), INF_T), fill(all(ma), -INF_T);
            tmp = -INF_T;
            dfs(i, 0, 0);

            //rep(i, 2) cout << mi[i] << ' ' << ma[i] << '\n';
            //cout << tmp << '\n';
            
            if(tmp != -INF_T){
                vector<T> check;
                check.eb(tmp+mi[0]), check.eb(tmp+ma[0]);
                check.eb(-tmp+mi[1]), check.eb(-tmp+ma[1]);

                bool f1 = false, f2 = false;
                each(e, check){
                    if(e <= 0 || e > K)  f1 = true;
                    if(e == K) f2 = true;
                }

                if(f1){
                    cout << "0\n";
                    exit(0);
                }
                
                ans1.eb(f2? 1 : 0), ans2.eb(1);
            }
            else{
                T L1 = 1-mi[0], R1 = K-ma[0];
                T L2 = ma[1]-K, R2 = mi[1]-1;
                T L = max(L1, L2), R = min(R1, R2);
                if(R < L){
                    cout << "0\n";
                    exit(0);
                }

                int t = 0;
                if(L == L2) t++;
                if(R == R1 && R != L) t++;
                ans1.eb(t), ans2.eb(R-L+1);
                //cout << t << ' ' << R-L+1 << '\n';
            }
        }

        mint ans = 1, rem = 1;
        rep(i, sz(ans1)){
            ans *= ans2[i], rem *= ans2[i]-ans1[i];
        }

        cout << ans-rem << '\n';
    }
};

int main(){
    int N, M; cin >> N >> M >> K;

    Weighted_Graph<ll> G(N);

    rep(i, M){
        int u, v, w; cin >> u >> v >> w; u--, v--;
        G.add_edge(u, v, w);
    }

    G.solve();
}
0