7.24〜7.28

最近カッコウは、問題を解決するには、多くの問題だ、私は鍋のアップを埋めます!

グレートマラソン

不滅のタイトル。

まず、2点の最短の前処理

そして、最後に金メダルと銅メダル最初の列挙は、我々は金、銀を得ることができない各プレイヤーを決定することができます

そして、DPを考えます

\(DP [I] [J ] [K] \) 選択表す\(Iは\)個体、現在(J \)\金、\(K \)銀のプログラム番号

コードの特定の実装を参照してください。

ll f[N][N] ;
int g[N][N], Min[N], Max[N] ;
bool gold[N], silver[N], bronze[N] ;
int n, m, g1, g2, s1, s2 ;
ll ans ;

signed main() {
    scanf("%d%d", &n, &m) ;
    ass(g, 0x3f) ;
    rep(i, 1, n) g[i][i] = 0 ;
    rep(i, 1, m) {
        int a, b, c ; scanf("%d%d%d", &a, &b, &c) ;
        g[a][b] = g[b][a] = min(g[a][b], c) ;       
    }
    rep(k, 1, n) rep(i, 1, n) rep(j, 1, n) chmin(g[i][j], g[i][k] + g[k][j]) ;
    rep(i, 1, n) {
        Min[i] = INF ; Max[i] = 0 ;
        rep(j, 1, n)
        if (i != j) {
            g[i][j] = g[i][j] * 60 + i ;
            chmax(Max[i], g[i][j]) ; chmin(Min[i], g[i][j]) ;
        }
    }
    scanf("%d%d%d%d", &g1, &g2, &s1, &s2) ;
    ans = 0 ;
    rep(bst, 1, n) // gold last (ignore the vars' name)
    rep(wst, 1, n) // bronze first
    if (wst != bst && Min[bst] < Max[wst]) {
        rep(i, 1, n) {
            gold[i] = Min[i] <= Min[bst] ;
            bronze[i] = Max[i] >= Max[wst] ;
            silver[i] = false ;
            rep(j, 1, n) 
            if (i != j && g[i][j] > Min[bst] && g[i][j] < Max[wst]) {
                silver[i] = true ;
                break ;
            }
        }
        gold[bst] = true ; silver[bst] = bronze[bst] = false ;
        gold[wst] = silver[wst] = false ; bronze[wst] = true ;
        clr(f) ;
        f[0][0] = 1 ;
        rep(k, 1, n)
        per(i, n, 0)
        per(j, n, 0)
        if (f[i][j]) {
            if (gold[k]) add(f[i + 1][j], f[i][j]) ;
            if (silver[k]) add(f[i][j + 1], f[i][j]) ;
            if (!bronze[k]) f[i][j] = 0 ;
        } 
        rep(i, g1, g2)
        rep(j, s1, s2)
        add(ans, f[i][j]) ;
    }
    printf("%lld\n", ans) ;
    return 0 ;
}

バスステーションの破棄

人々は偽である練習の最小カットを書きます

それはvjudgeデータハックを与えられています

ダウンロード

しかし、貪欲(欲がネットワークフローの本質である)拒否されている、私たちは別の方法を見つけることができます

明らかに、信頼性の低いDP。(これは神にすることができた場合)

けれども- \(<= 50 \ n)は、それが唯一の暴力唯一の方法!

オン!検索!

検索がそれを言ったことはなかっただろうどのように(コードを見に行きます)

反復深化のセットによって800ms

なぜを検索!

  1. より多くのプログラムを削除することができますが、最短経路は、まだ比較的大きいですが、私たちの検索は、層の多くない場合
  2. 最短時間の短縮は、より深い層の数が、少なくなり、削除することができるエッジの数が、より多くの我々は、距離に成功した場合

だから、これはの検索では、私たちの自信の源であります

int n, m, p, highest ;
int pre[N] ;
vi e[N] ;
int road[N][N] ;
bool del[N] ;
bool flg ;

void bfs() {
    queue <int> q ;
    clr(pre) ; pre[1] = -1 ;
    q.push(1) ;
    while (!q.empty()) {
        int cur = q.front() ; q.pop() ;
        rep(i, 0, siz(e[cur]) - 1) {
            int to = e[cur][i] ;
            if (!del[to] && !pre[to]) {
                pre[to] = cur ;
                q.push(to) ;
            }
        }
    }
}

void dfs(int x) {
    bfs() ;
    if (!pre[n]) {
        flg = 1 ;
        return ;
    }
    int num = 0 ;
    for (int i = n; i != -1; i = pre[i]) road[x][++num] = i ;
    if (num - 1 > p) {
        flg = 1 ;
        return ;
    }
    if(x > highest) return ;
    per(i, num - 1, 2) {
        del[road[x][i]] = 1 ;
        dfs(x + 1) ;
        del[road[x][i]] = 0 ;
    }
}

void init() {
    flg = 0 ;
    rep(i, 1, n) e[i].clear() ;
}

signed main() {
    while (scanf("%d%d%d", &n, &m, &p) != EOF && n) {
        init() ;
        rep(i, 1, m) {
            int u, v ; scanf("%d%d", &u, &v) ;
            e[u].pb(v) ;
        }
        rep(i, 0, n - 2) {
            highest = i ;
            clr(del) ;
            dfs(1) ;
            if (flg) break ;
        }
        printf("%d\n", highest) ;
    }
    return 0 ;
}

DrawingBlackCrosses

あなたの叔父は、圧力dpのようなものです

どのようにQAQを理解していませんでした

おそらく、削除してから転送する各黒格子縞(?)の列と行を列挙するかどうか

妖精コード(ORZ)を提供

#define bitcnt(x) __builtin_popcount(x)

class DrawingBlackCrosses {
public:
    int n, m, tot ;
    int f[N][N], sumx[N], sumy[N] ;
    bool validx[N], validy[N] ;
    vii black ;
    void reduce(int &x) { x += x >> 31 & mod ; }
    bool check(int msk) {
        rep(i, 0, n - 1) sumx[i] = 0 ;
        rep(i, 0, m - 1) sumy[i] = 0 ;
        rep(i, 0, tot - 1) 
        if (msk & (1 << i)) {
            sumx[black[i].fi]++ ;
            sumy[black[i].se]++ ;
        }
        int a = 0, b = 0 ;
        rep(i, 0, n - 1)
        if (!a) a = sumx[i] ;
        else if (sumx[i] && a != sumx[i]) return 0 ;
        rep(i, 0, m - 1)
        if (!b) b = sumy[i] ;
        else if (sumy[i] && b != sumy[i]) return 0 ;
        return (a == 0 && b == 0 || b - a == n - m) && a * b == bitcnt(msk) ; 
    }
    bool check(int S0, int S1) {
        rep(i, 0, tot - 1)
        if (S0 & (1 << i))
        rep(j, 0, tot - 1)
        if (S1 & (1 << j))
        if (black[i].fi == black[j].fi || black[i].se == black[j].se) 
        return 0 ;
        rep(i, 0, tot - 1)
        if (S1 & (1 << i))
        rep(j, i + 1, tot)
        if (S1 & (1 << j))
        if (black[i].fi == black[j].fi || black[i].se == black[j].se) 
        return 0 ;
        return 1 ;
    }
    int count(vector <string> field) {
        n = siz(field) ;
        m = siz(field[0]) ;
        rep(i, 0, n) f[i][0] = 1 ;
        rep(i, 0, m) f[0][i] = 1 ;
        rep(i, 1, n)
        rep(j, 1, m)
        f[i][j] = mulv(mulv(f[i - 1][j -1], i), j) ;
        rep(i, 0, n - 1)
        rep(j, 0, m - 1)
        if (field[i][j] == 'B') 
        black.pb(mp(i, j)) ;
        tot = siz(black) ;
        int ans = 0 ;
        rep(msk0, 0, (1 << tot) - 1)
         if (check(msk0))
         rep(msk1, 0, (1 << tot) - 1)
         if (check(msk0, msk1)) {
            clr(validx) ; clr(validy) ;
            rep(i, 0, tot - 1)
            if (msk0 & (1 << i))
            validx[black[i].fi] = 1, validy[black[i].se] = 1 ;
            rep(i, 0, tot - 1)
            if (msk1 & (1 << i))
            validx[black[i].fi] = 1, validy[black[i].se] = 1 ;
            int a = n, b = m ;
            rep(i, 0, n - 1) a -= validx[i] ;
            rep(i, 0, m - 1) b -= validy[i] ;
            int val = f[a][b], step = min(a, b) ;
            rep(i, 1, bitcnt(msk1)) mul(val, step + i) ;
            if (__builtin_parity(msk1)) sub(ans, val) ;
            else add(ans, val) ;
         }
        return ans ;
    }
} sol ;

Google Codeのジャム

良い良いタイトル

あなたは貪欲な戦略の1種類を要約することができるはずです

のみを考えてみましょう(0 <P_I <1 \) \ 大きなテストデータを

(どのような地獄、それについて理解し共に生きる)の並べ替えの順序を完了するために、隣接する二つの優先順位トピックを考えてみましょう

それがされている場合は(I、Jを\)\、もし\(私は\)(J \)\前に、あなたが満たしている必要があります。

\ [(T_I + T_J)(1-P_j)+ T_I(1-P_I)P_j <(T_I + T_J)(1-P_I)+ T_J(1-P_j)P_I \\ -P_j * T_J-T_I * P_j * P_I <-P_i * T_I-T_J * P_I * P_j \\ T_I * P_I(1-P_j)<T_J * P_j(1-P_I)\\ T_I * P_I /(1-P_I)<T_J * P_j(1-P_j )\]

私たちは、導入された\を(私は\)\(j個\)条件が前に満たすべき

これは、ことができます\(DP \) Aを

\(DP [I] [J ] [0/1] \) 私たちは前に考えられていることを意味し(私は\)\問題、我々は現在過ごす\(jは\)が分/予想時間の最大スコアを達成することが期待されています

このカードの質問解の精度:その後、丸め、大きな整数を取る\(DPを\)

const int base = 1000000 ;
ll ss[N], sl[N], f[N], p[N], tl[N], ts[N] ;
int n, t, ord[N] ;
double pp[N], g[N] ;
double ans ;

bool cmp(int i, int j) {
    return (tl[i] + tl[j]) * (base - p[j]) * base + tl[i] * p[j] * (base - p[i]) <
           (tl[i] + tl[j]) * (base - p[i]) * base + tl[j] * p[i] * (base - p[j]) ;
}

void update(int x, ll v1, double v2) {
    if (v1 > f[x] || v1 == f[x] && v2 < g[x]) f[x] = v1, g[x] = v2 ;
}

signed main() {
    scanf("%d%d", &n, &t) ;
    rep(i, 1, n) {
        scanf("%lld%lld%lld%lld%lf", &ss[i], &sl[i], &ts[i], &tl[i], &pp[i]) ;
        ord[i] = i ;
        p[i] = (int) (pp[i] * base + 0.5) ;
    }
    sort(ord + 1, ord + n + 1, cmp) ;
    rep(_, 1, n) {
        int i = ord[_] ;
        per(j, t, 0) {
            if (j + ts[i] <= t) update(j + ts[i], f[j] + ss[i] * base, g[j] + ts[i]) ;
            if (j + ts[i] + tl[i] <= t)
            update(j + ts[i] + tl[i], f[j] + ss[i] * base + sl[i] * (base - p[i]), 
                    ts[i] + g[j] * pp[i] + (j + tl[i]) * (1 - pp[i])) ;
        }
    }
    ans = g[t] ;
    rep(i, 0, t)
    if (f[i] == f[t] && g[i] < ans)
    ans = g[i];
    printf("%.10lf %.10lf\n", (double) f[t] / base, ans) ;
    return 0 ;
}

銀河連合

DPの直接の木の根元部分

环2-ポインタ

胡口の選手がQAQを残しています

RoadsofKingdom

圧力DPのような方法ntmdです

ツリー?マージ?圧力枚 それだけで罰金(霧)を考えます

状態MSKのために、我々は、サブステート考える\を(S_1、S_2 MSK-S_1 = \) 繰り返しを避けるために、固定することができる\(U_1 \ S_1で、V_1の S_2で\ \)

\(S_1 = U_1、U_2、...、u_n \)
\(S_2 = V_1、V_2、...、V_M \)
\([MSK] F [S_1] * [S_2] F * \和F = \ ^ M limits_ {= 1、I}(P_ {U_1、V_I} * \ sum_ {S_2-V_Iにおけるx \}(1-P_ {U_1、X}))* \ prod_ {I = 2} ^ n個の\ prod_ { X S_2で\}(1-P_ {u_i、X})\)

それについての理解。式は本当に\(van♂\)

class RoadsOfKingdom {
public:
    int n ;
    double dp[M], f1[M][N], f2[M][N], prob[N][N] ;
    bool vis[M] ;

    double dfs(int msk) {
        if (vis[msk]) return dp[msk] ;
        int p1 = -1, p2 = -1 ;
        rep(i, 0, n - 1)
        if (msk & (1 << i)) {
            if (p1 == -1) p1 = i ;
            else if (p2 == -1) { p2 = i ; break ; } 
        }
        if (p2 == -1) return 1 ; // endings
        int Msk = msk ^ (1 << p1) ^ (1 << p2) ;
        double ans = 0 ;
        for (int nmsk = Msk;; nmsk = (nmsk - 1) & Msk) { 
            int msk1 = nmsk | (1 << p1) ;
            int msk2 = msk ^ msk1 ;
            double tmp = 1 ;
            rep(i, 0, n - 1)
            if (p1 != i && (msk1 & (1 << i))) 
            tmp *= f1[msk2][i] ;
            ans += dfs(msk1) * dfs(msk2) * f2[msk2][p1] * tmp ;
            if (!nmsk) break ;
        }
        vis[msk] = 1 ;
        return dp[msk] = ans ;
    }
    double getProbability(vector <string> roads) {
        n = siz(roads) ;
        rep(i, 0, n - 1)
        rep(j, 0, n - 1) 
        prob[i][j] = (roads[i][j] - '0') / 8.0 ;
        rep(i, 0, (1 << n) - 1) 
        rep(j, 0, n - 1) {
            f1[i][j] = 1 ; 
            f2[i][j] = 0 ;
            rep(k, 0, n - 1) 
            if (i & (1 << k)) {
                f1[i][j] *= (1 - prob[k][j]) ;
                f2[i][j] += f1[i ^ (1 << k)][j] * prob[j][k] ;
            }
        }
    //  cout << "???\n" ;
        return dfs((1 << n) - 1) ;
    }
} sol ;

Levkoと設定

元のルートQAQは何ですか

この問題は最初のカッコウ

街路樹

ツリーラインと暴力の番号の前に10時間がdpを維持します

#define ls(x) x << 1
#define rs(x) x << 1 | 1
 
struct tree {
    int f[N] ;
    void pushup(int p) { f[p] = max(f[ls(p)], f[rs(p)]) ; }
    void update(int p, int l, int r, int x, int y) {
        if (l == r) {
            f[p] = y ;
            return ;
        }
        int mid = l + r >> 1 ;
        if (x <= mid) update(ls(p), l, mid, x, y) ;
        else update(rs(p), mid + 1, r, x, y) ;
        pushup(p) ;
    }
    int query(int p, int l, int r, int x, int y) {
        if (x <= l && r <= y) return f[p] ;
        int mid = l + r >> 1, ans = 0 ;
        if (x <= mid) ans = max(ans, query(ls(p), l, mid, x, y)) ;
        if (y > mid) ans = max(ans, query(rs(p), mid + 1, r, x, y)) ;
        return ans ;
    }
};
 
tree f, g ; // pos, height
int n, q ;
int pos[N], height[N], a[N] ;
set<int> s ;
 
int main() {
    scanf("%d%d", &n, &q) ;
    int m = delta + 10010 ;
    while (q--) {
        int op ; scanf("%d", &op) ;
        if (op == 1) {
            int p, h ;
            scanf("%d%d", &p, &h) ; h += delta ;
            s.insert(p) ;
            pos[h] = p ; 
            height[p] = h ;
            per(i,h, h - 9) {
                if (!pos[i]) continue ;
                int now = pos[i] ;
                f.update(1, 1, n, now, 0) ;
                g.update(1, 1, m, i, 0) ;
            }
            per(i, h, h - 9) {
                if (!pos[i]) continue ;
                int now = f.query(1, 1, n, pos[i] + 1, n) + 1 ;
                f.update(1, 1, n, pos[i], now) ;
                g.update(1, 1, m, i, now) ;
            }
        } else {
            int k ; scanf("%d", &k) ;
            auto it = s.begin() ;
            int cnt = 0 ;
            while (cnt < k) a[++cnt] = *it, ++it ;
            --it ;
            s.erase(it) ;
            rep(i, 1, cnt) {
                if (!height[a[i]]) continue ;
                f.update(1, 1, n, a[i], 0) ;
                g.update(1, 1, m, height[a[i]], 0) ;
            }
            per(i, cnt - 1, 1) {
                if (!height[a[i]]) continue ;
                int now = g.query(1, 1, m, height[a[i]] + 1, m) + 1 ;
                f.update(1, 1, n, a[i], now) ;
                g.update(1, 1, m, height[a[i]], now) ;
            }
            pos[height[a[cnt]]] = 0 ;
            height[a[cnt]] = 0 ;
        }
        printf("%d\n", f.f[1]) ;
        delta-- ;
    }
    return 0 ;
}

TMDは、あまりにも多くの水私は書きたくない
同様の地下鉄のタイミングプラクティスに

vi g[N] ;
int att[N], die[N], rem[N] ;
int n, ans ;

pii solve(int p, int fa) {
    vii v ;
    rep(i, 0, siz(g[p]) - 1) {
        int to = g[p][i] ;
        if (to == fa) continue ;
        v.pb(solve(to, p)) ;
    }
    sort(all(v)) ;
    pii res ;
    res.se = max(att[p], rem[p] + die[p]) ;
    res.fi = res.se - die[p] - rem[p] ;
    per(i, siz(v) - 1, 0) {
        pii cur = v[i] ;
        int Rem = res.fi - cur.se ;
        if (Rem >= 0) res.fi = Rem + cur.fi ;
        else {
            res.se -= Rem ;
            res.fi = cur.fi ; 
        }
    }
    return res ;
} 

signed main() {
    int Case = 0 ;
    while (scanf("%d", &n) != EOF && n) {
        printf("Case %d: ", ++Case) ;
        rep(i, 1, n) scanf("%d%d%d", &att[i], &die[i], &rem[i]) ;
        rep(i, 1, n) g[i].clear() ;
        rep(i, 1, n - 1) {
            int x, y ; scanf("%d%d",&x, &y) ;
            g[x].pb(y) ; g[y].pb(x) ;
        } 
        ans = iinf ;
        rep(i, 1, n) {
            pii cur = solve(i, -1) ;
            chmin(ans, cur.se) ;
        }
        printf("%d\n", ans) ;
    }

    return 0 ;
}

AtcoDeerと絵画グラフ

群論。

まず加工点tarjanビス成分ユニコムの

リンク構成要素の一組のために、

  1. エッジ<ポイントの数は、任意の色を置くことができる場合
  2. 点=エッジの数は、バーンサイドの要求によって、環を有します
  3. エッジ>ポイントの数は、複数のリングがある、組み合わせの数は、用途を見出します
int fac[N], inv[N] ;
int dfn[N], low[N], stk[N] ;
int n, m, k, tim, top, ans ;
vi e[N] ;
set <int> s ;

int C(int n, int k) {
    return mulv(fac[n], mulv(inv[k], inv[n - k])) ;
}

int burnside(int n) {
    int s = 0 ;
    rep(i, 1, n) add(s, pw(k, __gcd(i, n))) ;
    mul(s, pw(n, mod - 2)) ;
    return s ;
}
void tarjan(int u) {
    dfn[u] = low[u] = ++tim ;
    stk[++top] = u ;
    rep(i, 0, siz(e[u]) - 1) {
        int to = e[u][i] ;
        if (!dfn[to]) {
            tarjan(to) ;
            chmin(low[u], low[to]) ;
            if (low[to] >= dfn[u]) {
                s.clear() ; int t, nn, mm = 0 ; 
                do {
                    t = stk[top--] ;
                    s.insert(t) ;
                } while (t != to) ; 
                s.insert(u) ;
                nn = siz(s) ;
                loop(it, s) 
                rep(i, 0, siz(e[*it]) - 1) 
                if (s.count(e[*it][i])) mm++ ;
                mm /= 2 ;
                if (mm < nn) mul(ans, k) ;
                if (nn == mm) mul(ans, burnside(mm)) ;
                if (nn < mm) mul(ans, C(mm + k - 1, k - 1)) ;
            }
        } else {
            chmin(low[u], dfn[to]) ;
        }
    }
}

signed main() {
    scanf("%d%d%d", &n, &m, &k) ;
    rep(i, 1, m) {
        int x, y ; scanf("%d%d", &x, &y) ;
        e[x].pb(y) ; e[y].pb(x) ;
    }
    fac[0] = 1 ;
    rep(i, 1, m + k) fac[i] = mulv(fac[i - 1], i) ;
    inv[m + k] = pw(fac[m + k], mod - 2) ;
    per(i, m + k, 1) inv[i - 1] = mulv(inv[i], i) ;
    ans = 1 ;
    rep(i, 1, n) if (!dfn[i]) tarjan(i) ;
    printf("%d\n", ans) ;
    return 0 ;
}

コンテスト

二部グラフ・マッチング

JT練習ダミーの神、それは何QAQを理解するために、いくつかのダミーをプラグインする方法ではありません

typedef vector <string> vst ;
class TheContest {
public:
    int vis[N], link[N] ;
    int g[N][N] ;
    int fix ;
    int dfs(int u) {
        if (u <= fix) return 0 ;
        rep(v, 0, N - 10) 
        if (g[u][v] && !vis[v]) {
            vis[v] = 1 ;
            if (!~link[v] || dfs(link[v])) {
                link[v] = u ;
                link[u] = v ;
                return 1 ;
            }
        }
        return 0 ;
    }
    int ans[N][N], used[N][N], use[N][N] ;
    int cnt[N] ;
    vst getSchedule(int n, int m) {
        int r = max(n, m) ;
        rep(i, 1, n) {
            clr(g) ; 
            rep(j, 1, m)
            rep(k, 1, r) {
                if (used[j][k]) continue ;
                g[j][r + k] = 1 ;
            }
            rep(j, m + 1, r)
            rep(k, 1, r) 
            if (m - cnt[k] < n - i + 1) 
            g[j][r + k] = 1 ;
            vi anss ;
            rep(j, 1, m) {
                rep(k, 1, r) 
                if (g[j][k + r] && !use[i][k]) {
                    bool ok = 1 ;
                    ass(link, -1) ;
                    rep(l, 0, siz(anss) - 1) link[l + 1] = anss[l] + r, 
                    link[anss[l] + r] = l + 1 ;
                    link[j] = k + r, link[k + r] = j ;
                    rep(l, j + 1, r) {
                        clr(vis) ;
                        fix = j ;
                        if (!dfs(l)) { ok = 0 ; break ; } 
                    }
                    if (ok) {
                        use[i][k] = 1 ;
                        anss.pb(k) ;
                        cnt[k]++ ;
                        break ;
                    }
                }
                ans[i][j] = anss.back() ;
                used[j][anss.back()] = 1 ;
            }
        }
        vst res(n, string(m, '0')) ;
        rep(i, 0, n - 1)
        rep(j, 0, m - 1) {
            if (ans[i + 1][j + 1] < 10) res[i][j] = '0' + ans[i + 1][j + 1] ;
            else if (ans[i + 1][j + 1] < 36) 
            res[i][j] = 'A' + ans[i + 1][j + 1] - 10 ;
            else res[i][j] = 'a' + ans[i + 1][j + 1] - 36 ;
        } 
        return res ;
    } 
} sol ;

地下鉄のタイミング

+ Dpのバイナリツリー

問題のカッコウソリューション


int f[N][M], tmp[M] ;
int n, mid ;
vii e[N] ;

int isok(int x) {
    if (x >= -mid && x <= mid) return 1 ;
    return 0 ;
}

void dfs(int x, int fa) {
    rep(i, 0, mid) f[x][i] = -iinf ;
    f[x][0] = 0 ;
    rep(i, 0, siz(e[x]) - 1) {
        int to = e[x][i].fi, w = e[x][i].se ;
        if (to == fa) continue ;
        dfs(to, x) ;
        rep(j, 0, mid) {
            tmp[j] = f[x][j] ;
            f[x][j] = -iinf ;
        }
        rep(j, 0, mid)
        if (tmp[j] != -iinf) 
        rep(k, 0, mid)
        if (f[to][k] != iinf) {
            if (isok(j + k - w) && isok(tmp[j] + f[to][k] - w)) 
            chmax(f[x][max(j, k - w)], min(tmp[j], f[to][k] - w)) ;
            w -= 60 ;
            if (isok(j + k - w) && isok(tmp[j] + f[to][k] - w))
            chmax(f[x][max(j, k - w)], min(tmp[j], f[to][k] - w)) ;
            w += 60 ;
        }
    }
}

bool check(int mid) {
    dfs(1, 0) ;
    rep(i, 0, mid) if (f[1][i] > -iinf) return false ;
    return true ;
}

signed main() {
    int Case = 0 ;
    while (scanf("%d", &n) && n) {
        rep(i, 1, n) e[i].clear() ;
        rep(i, 1, n - 1) {
            int u, v, w ; scanf("%d%d%d", &u, &v, &w) ;
            w %= 60 ;
            e[u].pb(mp(v, w)) ;
            e[v].pb(mp(u, w)) ;
        }
        int l = -1, r = 120 ;
        while (l + 1 < r) { // 二分最小的代价 
            mid = (l + r) >> 1 ;
            dfs(1, 0) ;
            if (check(mid)) l = mid ;
            else r = mid ;
        }
        printf("Case %d: %d\n", ++Case, r) ;
    }   

    return 0 ;
}

私の悪いです

言うことはシミュレーションのものではありません

そして、暴力をチェック精力的に列挙

古代コード

#include <iostream>
#include <string>
#include <string.h>
#include <stdlib.h>
using namespace std;
struct dat_edge {
    int aim, last;
} edge[201];

int n, m, k, inde[101], coun[101], tmp_coun[101], pl[101], len_edge, num_key, key[300][101];
char kind[101];

void insert_edge(int x, int y) {
    len_edge++;
    edge[len_edge].aim = y;
    edge[len_edge].last = pl[x];
    pl[x] = len_edge;
}

void init(int o, string z) {
    int p, i, num;
    string t;
    p = 1;
    z += ' ';
    for (i = 1; i < z.length(); i++)
        if (z[i] == ' ') {
            t = z.substr(p, i - p);
            if (t[0] == 'i')
                num = 0;
            else
                num = n;
            if (t.length() == 2)
                num += t[1] - '0';
            else {
                num += (t[1] - '0') * 10 + t[2] - '0';
            }
            coun[o]++;
            insert_edge(num, o);
            p = i + 1;
        }
}

bool solve(int key[], int poi, int sta) {
    int i, p, o, w, tmp, que[101], f[101];
    for (i = 1; i <= n + m + k; i++) {
        f[i] = 0;
    }
    for (i = 1; i <= n; i++) f[i] = key[i];
    for (i = 1; i <= m; i++) {
        if (kind[i] == 'a')
            f[i + n] = 1;
        else
            f[i + n] = 0;
    }
    o = n;
    w = 0;
    for (i = 1; i <= n; i++) que[i] = i;
    while (w < o) {
        w++;
        if (que[w] == poi) {
            if (sta == 2)
                f[que[w]] = !f[que[w]];
            else
                f[que[w]] = sta;
        }
        p = pl[que[w]];
        while (p != -1) {
            coun[edge[p].aim]--;
            if (coun[edge[p].aim] == 0) {
                que[++o] = edge[p].aim;
            }
            tmp = edge[p].aim;
            if (kind[tmp - n] == 'a') {
                if (f[que[w]] == 0)
                    f[tmp] = 0;
            } else if (kind[tmp - n] == 'o') {
                if (f[que[w]] == 1)
                    f[tmp] = 1;
            } else if (kind[tmp - n] == 'x') {
                f[tmp] = f[tmp] ^ f[que[w]];
            } else {
                f[tmp] = !f[que[w]];
            }
            p = edge[p].last;
        }
    }
    for (i = 1; i <= n + m + k; i++) coun[i] = tmp_coun[i];
    for (i = 1; i <= k; i++) {
        if (f[inde[i] + n] != key[n + i])
            return false;
    }
    return true;
}

void work(int t) {
    int i, j, p, ans1, ans2, coun_ans;
    bool ok = true;
    for (i = 1; i <= num_key; i++) {
        if (!solve(key[i], -1, -1)) {
            ok = false;
            break;
        }
    }
    if (ok) {
        cout << "Case " << t << ": No faults detected\n";
        return;
    }
    ans1 = ans2 = coun_ans = 0;
    for (i = 1; i <= m; i++) {
        for (j = 0; j <= 2; j++) {
            ok = true;
            for (p = 1; p <= num_key; p++) {
                ok = solve(key[p], i + n, j);
                if (!ok)
                    break;
            }
            if (ok) {
                ans1 = i;
                ans2 = j;
                coun_ans++;
            }
        }
    }
    if (coun_ans != 1) {
        cout << "Case " << t << ": Unable to totally classify the failure\n";
        return;
    }
    if (ans2 == 2) {
        cout << "Case " << t << ": Gate " << ans1 << " is failing; output inverted\n";
        return;
    }
    if (ans2 == 0) {
        cout << "Case " << t << ": Gate " << ans1 << " is failing; output stuck at 0\n";
        return;
    }
    if (ans2 == 1) {
        cout << "Case " << t << ": Gate " << ans1 << " is failing; output stuck at 1\n";
        return;
    }
}

int main() {
    int t, i, j;
    string z;
    t = 0;
    while (cin >> n >> m >> k && n + m + k != 0) {
        t++;
        memset(coun, 0, sizeof(coun));
        len_edge = -1;
        for (i = 1; i <= n + m + k; i++) pl[i] = -1;
        for (i = 1; i <= m; i++) {
            cin >> kind[i];
            getline(cin, z);
            init(i + n, z);
        }
        for (i = 1; i <= n + m + k; i++) tmp_coun[i] = coun[i];
        for (i = 1; i <= k; i++) cin >> inde[i];
        cin >> num_key;
        for (i = 1; i <= num_key; i++)
            for (j = 1; j <= n + k; j++) cin >> key[i][j];
        work(t);
    }
    return 0;
}

万里の長城ゲーム

ちょっとちょっと私は、ネットワークフローが好き

不滅\(YCS \)圧力形で\(DP \)(F ** ITをK)、この2番目の質問

私のチキン料理は流れの費用がかかります

暴力は32状態決勝まで列挙します

  1. スーパースーパーは、ソースとシンクを確立します
  2. すべてのターゲット・ノードとスーパー為替さえエッジ\((0,1)\)
  3. 最初のエッジと参加するスーパーソースノード\((0,1)\)
  4. 最初のノードと宛先ノードも、全ての辺\((DIS(I、J )、\ infを)\)
  5. 最小コスト最大流量ラン
int n, m, cur, ans, top, s = 31, t = 32 ;
int head[N], pre[N], x[N], y[N], vis[N], dis[N] ;

struct Edge {
    int fr, to, nxt, val, len ; 
} e[M] ;

void add(int a, int b, int c, int d) {
    e[++top] = (Edge) {a, b, head[a], c, d}  ; head[a] = top ;
    e[++top] = (Edge) {b, a, head[b], -c, 0} ; head[b] = top ;
}

void init() {
    clr(head) ; top = 1 ;
    cur = 0 ;
}

int spfa() {
    queue <int> q ; while (!q.empty()) q.pop() ;
    ass(dis, 0x3f) ; clr(pre) ;
    q.push(s) ; dis[s] = 0 ;
    bool flg = 0 ;
    while (!q.empty()) {
        int u = q.front() ; q.pop() ;
        if (u == t) flg = 1 ;
        vis[u] = false ;
        cont(i, u) {
            int to = e[i].to ;
            if (!e[i].len) continue ;       
            if (dis[u] + e[i].val < dis[to]) {
                dis[to] = dis[u] + e[i].val ;
                pre[to] = i ;
                if (!vis[to]) {
                    vis[to] = 1 ;
                    q.push(to) ;
                }
            }
        }
    }
    return flg ;
}

void EK() {
    while (spfa()) {
        for (int i = pre[t]; i; i = pre[e[i].fr]) {
            e[i].len-- ; e[i ^ 1].len++ ;
            cur += e[i].val ;
        }
    }
    chmin(ans, cur) ;
}
 
void horizontal(int l) {
    init() ;
    rep(i, 1, n) add(i, t, 0, 1) ;
    rep(i, 1, n) {
        add(s, i + n, 0, 1) ;
        rep(j, 1, n) add(i + n, j, abs(x[i] - l) + abs(y[i] - j), 100) ;
    }
    EK() ;
}

void vertical(int l) {
    init() ;
    rep(i, 1, n) add(i, t, 0, 1) ;
    rep(i, 1, n) {
        add(s, i + n, 0, 1) ;
        rep(j, 1, n) add(i + n, j, abs(x[i] - j) + abs(y[i] - l), 100) ;
    }
    EK() ;
}

void diagonal() {
    init() ;
    rep(i, 1, n) add(i, t, 0, 1) ;
    rep(i, 1, n) {
        add(s, i + n, 0, 1) ;
        rep(j, 1, n)
        add(i + n, j, abs(x[i] - j) + abs(y[i] - (n - j + 1)), 100) ;
    }
    EK() ;
    init() ;
    rep(i, 1, n) add(i, t, 0, 1) ;
    rep(i, 1, n) {
        add(s, i + n, 0, 1) ;
        rep(j, 1, n)
        add(i + n, j, abs(x[i] - j) + abs(y[i] - j), 100) ;
    }
    EK() ;
}

signed main() {
    int Case = 0 ;
    while (scanf("%d", &n) != EOF && n) {
        rep(i, 1, n) scanf("%d%d", &x[i], &y[i]) ;
        ans = iinf ;
        rep(i, 1, n) horizontal(i) ;
        rep(i, 1, n) vertical(i) ;
        diagonal() ;
        printf("Board %d: %d moves required.\n\n", ++Case, ans) ;
    }
    return 0 ;
}

三角形の戦い

ハーフGG

永遠の文字列

\(KMP + DP \)裸のタイトル

\(\ mathsf {ローリング〜ハッシュ } \) と\(\ mathsf {Z〜ファンクション } \) も行


char s[N], t[N] ;
int n, m, k, ans ;
int fail[N], dp[N] ;

signed main() {
    scanf("%s%s", s + 1, t + 1) ;
    k = strlen(s + 1), n = k, m = strlen(t + 1) ; 
    while (n < m * 2) {
        rep(i, 1, n) s[n + i] = s[i] ;
        n *= 2 ;
    }
    rep(i, 1, n) s[n + i] = s[i] ; n *= 2 ;
    fail[0] = -1 ;
    rep(i, 1, m) {
        int j = i - 1 ;
        for (; j && t[fail[j] + 1] != t[i]; j = fail[j]) ;
        fail[i] = fail[j] + 1 ; 
    }
    int j = 0 ;
    rep(i, 1, n) {
        for (; ~j && s[i] != t[j + 1]; j = fail[j]) ;
        j++ ;
        if (j == m) dp[i] = dp[i - m] + 1, chmax(ans, dp[i]) ;
    }
    if (ans >= n / m - 1) ans = -1 ;
    printf("%d\n", ans) ;
    return 0 ;
}

おすすめ

転載: www.cnblogs.com/harryhqg/p/SXBDay2.html