板子1

Dijkstra:

int cnt, head[maxn]; ll dis[maxn];
struct Edge {
    int v, next; ll w; //记住这里改顺序下面push进队一定要改!
    bool operator < (const Edge &rhs) const {
        return w > rhs.w;
    }
} e[maxn*4];

void add(int u, int v, ll co) {
    e[cnt].v = v;
    e[cnt].w = co;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

void init() {
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void dij(int s, int len) {
    priority_queue<Edge> pq;
    for (int i = 1; i <= len; i++)
        dis[i] = inf;
    bool vis[maxn] = {0};
    dis[s] = 0;
    pq.push((Edge){s, 0, 0});
    while (!pq.empty()) {
        Edge tmp = pq.top(); pq.pop();
        if (vis[tmp.v]) continue;
        vis[tmp.v] = 1;
        for (int i = head[tmp.v]; ~i; i = e[i].next) {
            Edge u = e[i];
            if (dis[u.v] > dis[tmp.v] + u.w) {
                dis[u.v] = dis[tmp.v] + u.w;
                pq.push((Edge){u.v, 0, dis[u.v]});
            }
        }
    }
}

  

组合数打表:

void init() {
    for (int i = 0; i < maxn; i++) {
        for (int j = 0; j <= i; j++) {
            if (j == 0) c[i][j] = 1;
            else
                c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod; // C[i][j]表示i里面挑选j个
        }
    }
}

LIS

int d[maxn], a[maxn];
void LIS() {
    vector<int> v;
    for (int i = 1; i <= n; i++) {
        int si = v.size();
        int p = lower_bound(v.begin(), v.end(), a[i]) - v.begin(); //lower是严格 upper是不严格
        if (p == si) v.push_back(a[i]);
        else {
            v[p] = a[i];
        }
        d[i] = p + 1;
    }
}

LCA(ST表):

vector<int> G[maxn];
int ver[maxn*2], dp[maxn*2][33], tot, R[maxn*2], vis[maxn], first[maxn];
int n;

void dfs(int x, int dep) {
    vis[x] = 1, ver[++tot] = x; R[tot] = dep; first[x] = tot;
    for (int i = 0; i < G[x].size(); i++) {
        int u = G[x][i];
        if (vis[u]) continue;
        dfs(u, dep+1);
        ver[++tot] = x; R[tot] = dep;
    }
}

void RMQ_init(int len) {
    for (int i = 1; i <= len; i++) dp[i][0] = i;
    for (int j = 1; (1<<j) <= len; j++) {
        for (int i = 1; i + (1 << j) - 1 <= len; i++) {
            int a = dp[i][j-1], b = dp[i+(1<<(j-1))][j-1];
            dp[i][j] = R[a] < R[b] ? a : b;
        }
    }
}

int RMQ(int l, int r) {
    int k = 0;
    while ((1 << (k+1)) <= r-l+1) k++;
    int a = dp[l][k], b = dp[r-(1<<k)+1][k];
    return R[a] < R[b] ? a : b;
}

int LCA(int u, int v) {
    int x = first[u], y = first[v];
    if (x > y) swap(x, y);
    return ver[RMQ(x, y)];
}

void init() {
    tot = 0;
    for (int i = 1; i <= n; i++) G[i].clear();
    memset(vis, 0, sizeof(vis));
}


void solve() {
    int m;
    cin >> n >> m;
    init();
    for (int i = 1; i < n; i++) {
        int u, v; scanf("%d%d", &u, &v);
        G[u].push_back(v);
    }
    dfs(1, 1);
    RMQ_init(tot);
    for (int i = 1; i <= m; i++) {
        int u, v; scanf("%d%d", &u, &v);
        int x = LCA(u, v);
        cout << x << endl;
    }
}

二分图判定 + 最大匹配(邻接表初识)

int n, m, head[maxn], cnt, col[maxn], link[maxn];
struct Edge {
    int to, next;
} e[maxn*maxn];

void add(int u, int v) {
    e[cnt].to = v;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

void init() {
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(col, -1, sizeof(col));
}

bool color(int u) {
    for (int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].to;
        if (col[v] == -1) {
            col[v] = !col[u];
            if (!color(v)) return false;
        }
        else if (col[v] == col[u]) return false;
    }
    return true;
}

bool dfs(int u) {
    for (int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].to;
        if (col[v]) continue;
        col[v] = 1;
        if (link[v] == -1 || dfs(link[v])) {
            link[v] = u;
            return true;
        }
    }
    return false;
}

int match() {
    int ans = 0;
    memset(link, -1, sizeof(link));
    for (int i = 1; i <= n; i++) {
        memset(col, 0, sizeof(col));
        if (dfs(i)) ans++;
    }
    return ans;
}

void solve() {
    while (cin >> n >> m) {
        init();
        for (int i = 1; i <= m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        int flag = 1;
        for (int i = 1; i <= n; i++) {
            if (col[i] == -1) {
                col[i] = 1;
                if (!color(i)) flag = 0;
            }
        }
        if (!flag) cout << "No\n";
        else {
            cout << match() / 2 << endl;
        }
    }
}

搞死小圆

void GAE() {
    int ans = 0;
    for (int i = 1, l = 1; i <= n && l <= m; i++, l++) { //i是行 l是列
        int flag = 0, j;
        int tmp = j; db maxx = -inf;
        for (int j = i; j <= n; j++) {
            if (a[j][l] > maxx) {
                tmp = j;
                maxx = a[j][l];
            }
        }
        j = tmp;
        if (cmp(a[j][l], 0) == 0) {
            i--; continue;
        }
       // ans++;
        for (int k = l; k <= m; k++)
            swap(a[i][k], a[j][k]);
        for (int k = 1; k <= n; k++) {
            if (k == i) continue;
            db xx = a[k][l] / a[i][l];  //倍数
            for (j = l; j <= m; j++) {
                a[k][j] -= a[i][j] * xx;
            }
        }
    }
   // cout << ans << endl;
}

  

点双联通分量 + 二分图判定(染色法, poj2942) 

int n, m, head[maxn], low[maxn], cnt, col[maxn], pre[maxn];
int ht[maxn][maxn], tim, sta[maxn*maxn], top, ans, can[maxn], kn[maxn];
struct Edge {
    int st, to, next, vis;
} e[maxn*maxn*2];

void add(int u, int v) {
    e[cnt].st = u;
    e[cnt].to = v;
    e[cnt].next = head[u];
    e[cnt].vis = 0;
    head[u] = cnt++;
}

void init() {
    tim = cnt = top = ans = 0;
    memset(head, -1, sizeof(head));
    memset(ht, 0, sizeof(ht));
    memset(pre, 0, sizeof(pre));
    memset(kn, 0, sizeof(kn));
}

bool color(int u) {
    for (int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].to;
        if (!can[v]) continue;
        if (col[v] == -1) {
            col[v] = !col[u];
            if (!color(v)) return false;
        }
        else if (col[v] == col[u]) return false;
    }
    return true;
}

void tarjan(int u, int fa) { 
    pre[u] = low[u] = ++tim;
    for (int i = head[u]; ~i; i = e[i].next) {
        int v = e[i].to;
        if (e[i].vis) continue;
        e[i].vis = e[i^1].vis = 1;
        if (!pre[v]) {
            sta[++top] = i;
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] >= pre[u]) {
                memset(can, 0, sizeof(can));
                int tmp;
                do {
                    tmp = sta[top--];
                    can[e[tmp].to] = 1;
                    can[e[tmp].st] = 1;
                } while (e[tmp].st != u);
                memset(col, -1, sizeof(col));
                col[u] = 1;
                if (!color(u)) {
                    for (int j = 1; j <= n; j++)
                        if (can[j])
                            kn[j] = 1;
                }
            }
        }
        else if (v != fa) { // fa很重要,因为如果是桥的话 就会更新到父节点了
            low[u] = min(low[u], pre[v]);
            sta[++top] = i;
        }
    }
}

void solve() {
    while (cin >> n >> m) {
        if (!n && !m) break;
        init();
        for (int i = 1; i <= m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            ht[u][v] = ht[v][u] = 1;
        }
        for (int i = 1; i <= n; i++)
            for (int j = i+1; j <= n; j++)
                if (!ht[i][j])
                    add(i, j), add(j, i);
        for (int i = 1; i <= n; i++) {
            if (!pre[i]) {
                tarjan(i, -1);
            }
        }
        for (int i = 1; i <= n; i++)
            if (kn[i]) ans++;
        cout << n - ans << endl;
    }
}

2维凸包

struct Node {
    int x, y, id;
} po[maxn];
int n, l;
int flag;

bool cmp(const Node &a, const Node &b) {
    if (a.x == b.x) return a.y < b.y;
    return a.x < b.x;
}

int mul(int x1, int x2, int y1, int y2) {
    return x1 * y2 - x2 * y1;
}
Node S[maxn];
int top;

void ch(Node cur) {
    while (top > flag) {
        Node po1 = S[top];
        Node po2 = S[top-1];
        int x1 = po1.x - po2.x, y1 = po1.y - po2.y;
        int x2 = cur.x - po2.x, y2 = cur.y - po2.y;
        if (mul(x1, x2, y1, y2) >= 0) {
            top--;
        }
        else break;
    }
    S[++top] = cur;
}

void solve() {
    while (cin >> n >> l) {
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &po[i].x, &po[i].y);
            po[i].id = i;
        }
        sort(po+1, po+1+n, cmp);
        top = 0;
        flag = 1;
        for (int i = 1; i <= n; i++) {
            ch(po[i]);
        }
        flag = top;
        for (int i = n-1; i >= 1; i--) {
            ch(po[i]);
        }
        top--;
        for (int i = 1; i <= top; i++) { 
                ...
        }
    }
}

  

LCA(tarjan)

struct Edge{
    int v, c;
};
vector<Edge> G[maxn], qur[maxn];
int fa[maxn], dis[maxn], n, ans[205];
bool vis[maxn];

int Find(int x) {
    return fa[x] = fa[x] == x ? x : Find(fa[x]);
}

void init() {
    for (int i = 1; i <= n; i++) G[i].clear(), qur[i].clear(), fa[i] = i;
    dis[1] = 0; memset(vis, 0, sizeof(vis));
}

void Tanjar_LCA(int x) {
    vis[x] = 1;
    for (int i = 0; i < G[x].size(); i++) {
        int hh = G[x][i].c, u = G[x][i].v;
        if (vis[u]) continue;
        dis[u] = dis[x] + hh;
        Tanjar_LCA(u);
        fa[u] = Find(x);
    }
    for (int i = 0; i < qur[x].size(); i++) {
        int u = qur[x][i].v;
        if (!vis[u]) continue;
        int lca = Find(u);
        ans[qur[x][i].c] = dis[x] + dis[u] - 2*dis[lca];
    }
}

求割顶(tarjan)

int n, low[maxn], pre[maxn], tim, ans;
vector<int> G[maxn];
bool iscut[maxn];

void init() {
    ans = 0, tim = 0;
    for (int i = 1; i <= n; i++) G[i].clear();
    memset(iscut, false, sizeof(iscut));
    memset(pre, 0, sizeof(pre));
}

void tarjan(int u, int fa) {
    low[u] = pre[u] = ++tim;
    int child = 0;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (!pre[v]) {
            child++;
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] >= pre[u])
                iscut[u] = true;
        }
        else if (fa != v && pre[v] < pre[u])
            low[u] = min(low[u], pre[v]);
    }
    if (fa < 0 && child == 1)
        iscut[u] = false;
}

边双联通分量(tarjan, poj3352)

struct Edge {
    int u, v;
} e[maxn<<1];
int n, m, low[maxn], pre[maxn], tim, ebcc_cnt, du[maxn];
vector<int> G[maxn];
int isbri[maxn<<1];

void init() {
    ebcc_cnt = tim = 0;
    for (int i = 1; i <= n; i++) G[i].clear();
    memset(isbri, 0, sizeof(isbri));
    memset(pre, 0, sizeof(pre));
    memset(du, 0, sizeof(du));
}

void tarjan(int u, int fa) {
    low[u] = pre[u] = ++tim;
    int child = 0;
    for (int i = 0; i < G[u].size(); i++) {
        int tmp = G[u][i];
        int v = e[tmp].v;
        if (!pre[v]) {
            child++;
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
            if (low[v] > pre[u])
                isbri[tmp] = isbri[tmp^1] = true;
        }
        else if (fa != v) // fa很重要 对于桥
            low[u] = min(low[u], pre[v]);
    }
}

void dfs(int u) {
    pre[u] = ebcc_cnt;
    for (int i = 0; i < G[u].size(); i++) {
        int tmp = G[u][i];
        if (isbri[tmp]) continue;
        int v = e[tmp].v;
        if (pre[v]) continue;
        dfs(v);
    }
}

void find_ebcc() {
    tarjan(1, -1);
    memset(pre, 0, sizeof(pre));
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) {
            ebcc_cnt++;
            dfs(i);
        }
    }
}

void solve() {
    while (cin >> n >> m) {
        init();
        for (int i = 1; i <= m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            e[i<<1|1].u = u, e[i<<1|1].v = v;
            e[i<<1].u = v, e[i<<1].v = u;
            G[u].push_back(i<<1|1);
            G[v].push_back(i<<1);
        }
        find_ebcc();
        int tot = m<<1|1;
        for (int i = 1; i <= n; i++) G[i].clear();
        for (int i = 1; i <= tot; i += 2) {
            if (isbri[i]) {
                int u = e[i].v, v = e[i].u;
                du[pre[u]]++, du[pre[v]]++;
            }
        }
        int ans = 0;
        for (int i = 1; i <= ebcc_cnt; i++)
            if (du[i] == 1) ans++;
        if (ebcc_cnt == 1) cout << 0 << endl;
        else cout << (ans+1) / 2 << endl;
    }
}

  

 

 

线段树(删除了之后的第K个数)

struct TREE{
    ll l, r, val;
} tre[maxn*4];

void build(int id, int l, int r) {
    tre[id].l = l, tre[id].r = r;
    if (l == r) tre[id].val = 1;
    else {
        int mid = (l+r) >> 1;
        build(id<<1, l, mid);
        build(id<<1|1, mid+1, r);
        tre[id].val = tre[id<<1].val + tre[id<<1|1].val;
    }
}

ll query(int id, int pos) {
    int tmp;
    if (tre[id].l == tre[id].r) {
        tre[id].val = 0; return tre[id].l;
    }
    else {
        if (tre[id<<1].val >= pos) tmp = query(id<<1, pos);
        else tmp = query(id<<1|1, pos - tre[id<<1].val);
    }
    tre[id].val = tre[id<<1].val + tre[id<<1|1].val;
    return tmp;
}

线段树(单点更新)

struct TREE{
    int l, r, m, val;
} tre[maxn*4];
void build(int id, int l, int r) {
    tre[id].l = l, tre[id].r = r, tre[id].m = (l + r) >> 1;
    if (l == r)
        tre[id].val = 1;
    else {
        int mid = (l+r) >> 1;
        build(id<<1, l, mid);
        build(id<<1|1, mid+1, r);
       // tre[id].val = min(tre[id<<1].val, tre[id<<1|1].val);
    }
}

void update(int id, int pos, int val) {
    if (tre[id].l == tre[id].r) tre[id].val = val;
    else {
        int l = tre[id].l, r = tre[id].r;
        int mid = (l+r) >> 1;
        if (mid >= pos) update(id<<1, pos, val);
        else update(id<<1|1, pos, val);
        tre[id].val = min(tre[id<<1].val, tre[id<<1|1].val);
    }
}

int query(int id, int l, int r) {
    if (tre[id].l >= l && tre[id].r <= r) return tre[id].val;
    else {
        if (r <= tre[id].m) return query(id<<1, l, r);
        else if (l > tre[id].m) return query(id<<1|1, l, r);
        else return min(query(id<<1, l, tre[id].m), query(id<<1|1, tre[id].m+1, r));
    }
}

  

线段树(区间更新)

int a[maxn];
struct TREE{
    ll l, r, val, lazy;
    void fun(ll tmp) {
        lazy += tmp;
        val += (r - l + 1) * tmp;
    }
} tre[maxn*4];

void PushDown(int id) {
    if (tre[id].lazy) {
        tre[id<<1].fun(tre[id].lazy);
        tre[id<<1|1].fun(tre[id].lazy);
        tre[id].lazy = 0;
    }
}

void PushUp(int id) {
    tre[id].val = tre[id<<1].val + tre[id<<1|1].val;
}

void build(int id, int l, int r) {
    tre[id].l = l, tre[id].r = r, tre[id].lazy = 0;
    if (l == r) tre[id].val = a[l];
    else {
        int mid = (l+r) >> 1;
        build(id<<1, l, mid);
        build(id<<1|1, mid+1, r);
        PushUp(id);
    }
}

void update(int id, int st, int ed, int val) {
    int l = tre[id].l, r = tre[id].r;
    if (st <= l && ed >= r) tre[id].fun(val);
    else {
        PushDown(id);
        int mid = (l+r) >> 1;
        if (st <= mid) update(id<<1, st, ed, val);
        if (ed > mid) update(id<<1|1, st, ed, val);
        PushUp(id);
    }
}

ll query(int id, int st, int ed) {
    int l = tre[id].l, r = tre[id].r;
    if (st <= l && ed >= r) return tre[id].val;
    else {
        PushDown(id);
        int mid = (l+r) >> 1;
        ll sum1 = 0, sum2 = 0;
        if (st <= mid) sum1 = query(id<<1, st, ed);
        if (ed > mid) sum2 = query(id<<1|1, st, ed);
        PushUp(id);
        return sum1 + sum2;
    }
}

强连通分量+缩点

int n, m, low[maxn], pre[maxn], scc[maxn], scc_cnt, dfs_tim;
int in[maxn], out[maxn];
vector<int> G[maxn];
stack<int> S;

void init() {
    dfs_tim = scc_cnt = 0;
    memset(pre, 0, sizeof(pre));
    memset(scc, 0, sizeof(scc));
    memset(in, 0, sizeof(in));
    memset(out, 0, sizeof(out));
    for (int i = 1; i <= n; i++)
        G[i].clear();
}

void dfs(int x) {
    low[x] = pre[x] = ++dfs_tim;
    S.push(x);
    for (int i = 0; i < G[x].size(); i++) {
        int u = G[x][i];
        if (!pre[u]) {
            dfs(u);
            low[x] = min(low[x], low[u]);
        }
        else if (!scc[u])
            low[x] = min(low[x], pre[u]);
    }
    if (low[x] == pre[x]) {
        scc_cnt++;
        while (1) {
            int u = S.top(); S.pop();
            scc[u] = scc_cnt;
            if (u == x) break;
        }
    }
}

void solve() {
    for (int i = 1; i <= n; i++) {
        if (!pre[i]) dfs(i);
    }
    if (scc_cnt == 1) cout << 0 << endl;
    else {
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < G[i].size(); j++) {
                int u = G[i][j];
                if (scc[u] != scc[i]) {
                    in[scc[u]] = out[scc[i]] = 1;
                }
            }
        }
        int QAQ = 0, HH = 0;
        for (int i = 1; i <= scc_cnt; i++) {
            if (!in[i]) QAQ++;
            if (!out[i]) HH++;
        }
        cout << max(QAQ, HH) << endl;
    }
}

int main() {
    //cin.sync_with_stdio(false);
    //freopen("isharp.in", "r", stdin);
    //freopen("isharp.out", "w", stdout);
    int t; cin >> t;

    while (t--) {
        cin >> n >> m;
        init();
        for (int i = 1; i <= m; i++) {
            int u, v; scanf("%d%d", &u, &v);
            G[u].push_back(v);
        }
        solve();
    }
    return 0;
}

KMP(SCU 4438)

char pri[maxn];
char w[maxn], p[maxn];
int Next[maxn], now[maxn];

void getnext(char *s, int len) {
    int t1 = 0, t2;
    Next[0] = t2 = -1;
    while(t1 < len){
        if(t2 == -1 || s[t1] == s[t2])
            Next[++t1] = ++t2;
        else t2 = Next[t2];
    }
}

void kmp(char *s1, char *s2, int len1, int len2) {
    int k = 0, t = 0;
    for (int i = 0; i < len1; i++) {
        pri[k] = s1[i];
        while (t != -1 && s1[i] != s2[t]) t = Next[t];
        t++;
        now[k++] = t;
        if (t == len2) {
            k -= len2;
            t = now[k-1];
        }
    }
    pri[k] = 0;
}

  

 背包

<1>  01背包(w[i]代表重量,v[i]代表价值,V代表背包容量)
for(int i=0;i<N;i++)
            for(int j=V;j>=w[i];j--)
                dp[j]=max(dp[j-w[i]]+v[i],dp[j]);

<2> 完全背包(完全背包跟01背包的代码很像)
for(int i=0;i<N;i++)
            for(int j=w[i];j<=V;j++)
                dp[j]=max(dp[j-w[i]]+v[i],dp[j]);

<3> 多重背包

说起多重背包,可以用单调队列优化,也可以用二进制优化,目前只学了二进制优化方法,以后补上单调队列算法优化。

多重背包其实就是01背包与完全背包的结合题。(f[i].w代表重量,f[i].v代表价值,f[i].t代表数量,w代表背包容量)

在二进制优化那边我的代码写的有点繁琐,可以更简洁,就交给你们啦。 吐舌头 
for(int i=0;i<=k;i++)
    {
      int sum=f[i].w*f[i].t;
      if(sum>=w)	  //完全背包
      {
        for(int j=f[i].w;j<=w;j++)
          dp[j]=max(dp[j],dp[j-f[i].w]+f[i].v);
      }
      else	 //二进制优化转化成01背包求解
      {
        int aa=1,cc=1,m,g;
        while(cc<f[i].t)
        {
          m=aa*f[i].w;
          g=aa*f[i].v;
          aa*=2;
          cc+=aa;
          for(int j=w;j>=m;j--)
            dp[j]=max(dp[j],dp[j-m]+g);
        }
         m=(f[i].t-(cc-aa))*f[i].w;
         g=(f[i].t-(cc-aa))*f[i].v;
         for(int j=w;j>=m;j--)
          dp[j]=max(dp[j],dp[j-m]+g);
      }
    }

矩阵快速幂

struct Ma{
    ll n, m;
    ll a[30][30];
    void clear() {
        n = m = 0;
        memset(a, 0, sizeof(a));
    }
    Ma operator * (const Ma &b) const {
        Ma tmp;
        tmp.clear();
        tmp.n = n; tmp.m = b.m;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < b.m; j++) {
                for (int k = 0; k < m; k++) {
                    tmp.a[i][j] |= (a[i][k] * b.a[k][j]);
                    //tmp.a[i][j] %= mod;
                }
            }
        }
        return tmp;
    }
};

ll _pow(ll t) {
    Ma M, F, E;
    M.clear(), F.clear(),E.clear(); //  清空
    M.n = M.m = F.n = F.m = E.n = E.m = 3;  //大小
    F.a[0][0] = 1, F.a[0][1] = 0, F.a[0][2] = 1;  //F是初始矩阵、M是构造出的矩阵
    for (int i = 0; i < 3; i++) {
        E.a[i][i] = 1;
    }
    M.a[0][0] = 1, M.a[0][1] = 1, M.a[1][0] = 2;
    M.a[2][0] = 1, M.a[2][2] = 1;
    //  主要的
    while (t) {
        if (t & 1) E = M*E;
        M = M*M;
        t >>= 1;
    }
    F = F * E;
    return F.a[0][0] % mod;
}

  

状态压缩的背包:

void get_sta() {
    for (int i = 0; i < (1<<n); i++) {
        if (ok(i))
            sta[++len] = i, xx[i] = 1;
    }
}

int solve_bag() {
    for (int i = 1; i <= len; i++) {
        for (int j = (1<<n) - 1; j >= 0; j--) {
            if (!(sta[i] & j)) {
                dp[sta[i]|j] = min(dp[sta[i]|j], dp[j] + 1);
            }
        }
    }
    return dp[(1<<n)-1] == INF ? -1 : dp[(1<<n)-1];
}

MTSP

for (int i = 0; i < (1<<n); i++) {
        if (xx[i]) {
            for (int j = 0; j < n; j++) {
                if (i&(1<<j)) {
                    best[i] = min(best[i], en[j][i] + dis[j][0]);
                    for (int k = 0; k < n; k++) {
                        if (!(i&(1<<k))) {
                            en[k][i|(1<<k)] = min(en[k][i|(1<<k)], en[j][i] + dis[j][k]);
                        }
                    }
                }
            }
        }
    }
    for (int i = 1; i < (1<<n); i++)
        if (i&1)
            for (int j = i&(i-1); j; j = i&(j-1))
                best[i] = min(best[i], best[(i-j)|1] + best[j|1]);
    return best[(1<<n)-1];

 

posted @ 2016-09-14 16:04  ost_xg  阅读(423)  评论(0)    收藏  举报