zoukankan      html  css  js  c++  java
  • 暑假第十一测

    今天爆零了,roadblock是原题,结果还审错题了。。。

     

    题解

    第一题把最短路上的边提出来,然后跑最大流直到跑不动;但这样写比较麻烦;

    用最小费用最大流也可以过,比某些网络流还快,这东西也玄学;

    #include <bits/stdc++.h>
    
    using namespace std;
    const int maxn = 3010, maxm = 41000, inf = 1000000008;
    struct Netflow{
        int tot,head[maxn],maxflow,S,T,minlen;
        int inq[maxn],pre[maxn],pree[maxn],dis[maxn];
        struct edge{
            int to,f,w,nxt;
        }G[maxm];
        void init(int s, int t){
            S = s, T = t;
            tot = 1;
            memset(head,0,sizeof(head));
            maxflow = 0;
            minlen = inf;
        }
        void add(int u,int v,int f,int w){
            G[++tot].nxt = head[u];
            G[tot].to = v;
            G[tot].f = f;
            G[tot].w = w;
            head[u] = tot;
            G[++tot].nxt = head[v];
            G[tot].to = u;
            G[tot].f = 0;
            G[tot].w = -w;
            head[v] = tot;
        }
        void SPFA(){
            queue <int> Q;
            for(int i = 0; i <= T; i++)dis[i] = inf;
            memset(inq,0,sizeof(inq));
            Q.push(S);
            inq[S] = 1;
            dis[S] = 0;
    
            while(!Q.empty()){
                int u = Q.front();
                Q.pop();
                inq[u] = 0;
    
                for(int i = head[u]; i; i= G[i].nxt){
                    int v = G[i].to;
                    if(G[i].f && dis[v] > dis[u] + G[i].w){
                        dis[v] = G[i].w + dis[u];
                        if(!inq[v]){
                            Q.push(v);
                            inq[v] = 1;
                        }
                    }
                }
            }
            minlen = dis[T];
        }
        bool spfa(){
            queue <int> Q;
            for(int i = 0; i <= T; i++)dis[i] = inf;
            memset(inq,0,sizeof(inq));
           // memset(pre,0,sizeof(pre));
           // memset(pree,0,sizeof(pree));
    
            Q.push(S);
            inq[S] = 1;
            dis[S] = 0;
    
            while(!Q.empty()){
                int u = Q.front();
                Q.pop();
                inq[u] = 0;
    
                for(int i = head[u]; i; i= G[i].nxt){
                    int v = G[i].to;
                    if(G[i].f && dis[v] > dis[u] + G[i].w){
                        dis[v] = G[i].w + dis[u];
                        pre[v] = u;
                        pree[v] = i;
                        if(!inq[v]){
                            Q.push(v);
                            inq[v] = 1;
                        }
                    }
                }
            }
            return dis[T] == minlen;
        }
        void augment(){
            while(spfa()){
                int u = T, delta = inf;
                while(u != S){
                    delta = min(delta, G[pree[u]].f);
                    u = pre[u];
                }
                u = T;
                while(u != S){
                    G[pree[u]].f -= delta;
                    G[pree[u]^1].f += delta;
                    u = pre[u];
                }
                maxflow += delta;
            }
            printf("%d
    ",maxflow);
        }
    };
    
    
    int main()
    {
        freopen("roadblock.in","r",stdin);
        freopen("roadblock.out","w",stdout);
        int T,n,m;
        scanf("%d",&T);
        while(T--){
            Netflow Tr;
            scanf("%d%d",&n,&m);
            Tr.init(1,n);
            while(m--){
                int u, v, w;
                scanf("%d%d%d",&u,&v,&w);
                Tr.add(u, v, w, 1);
                Tr.add(v, u, w, 1);
            }
            Tr.SPFA();
            Tr.augment();
        }
    
        return 0;
    }
    View Code

    第二题:

    一道拓扑排序,我完全没看出来,在那里傻逼并查集了半天;

    可以知道一条路径中间忽略的车站等级一定更低,但是暴力建边复杂度是(m*n)不能过;

    所以就有了传说已久的线段树优化建边,学std写了一波,线段树从下往上建边,对于出现的一组要求我们就开一个新节点;

    至于无向图的线段树建边还要稍稍麻烦些,要开两棵树,有空看看吧

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 600005;
    int in[M], h[M], mark[M], dg[M], tot, idx, n, m, pos[M];
    struct edge{
        int v, nxt;
    }G[M * 10];
    void add(int u, int v){
        G[++tot].nxt = h[u]; G[tot].v = v; h[u] = tot; in[v]++;
    }
    
    struct Node {
        Node *ls , *rs;
        int id;
    }pool[M << 1], *root, *tail = pool;
    
    Node * build(int l = 1, int r = n){
        Node * nd = ++tail;  nd->id = ++idx; 
        if(l == r) mark[idx] = 1, pos[l] = idx;
        else {
            int mid = (l + r) >> 1;
            nd->ls = build(l, mid);
            add(nd->ls->id, nd->id);
            nd->rs = build(mid + 1, r);
            add(nd->rs->id, nd->id);
        }
        return nd;
    }
    #define Ls nd->ls, l, mid
    #define Rs nd->rs, mid+1, r
    void modify(int L, int R, int crtime, Node * nd = root, int l = 1, int r = n){
        if(L <= l && r <= R){
            add(nd->id, crtime);
        }
        else{
            int mid = (l + r) >> 1;
            if(L <= mid)modify(L, R, crtime, Ls);
            if(R > mid)modify(L, R, crtime, Rs);
        }
    }
    void solve(){
        int ans = 1;
        queue <int> q;
        q.push(0);
        for(int i = 1; i <= n; i++)
            if(!in[pos[i]]) q.push(pos[i]), dg[pos[i]] = 1;
        while(!q.empty()){
            int u = q.front(); q.pop();
            for(int i = h[u]; i; i = G[i].nxt){
                int v = G[i].v;
                in[v]--;
                dg[v] = max(dg[v], dg[u] + mark[v]);
                if(!in[v])q.push(v);
                ans = max(ans, dg[v]);
            }
            //for(int i = 1; i <= n; i++)printf("%d ", dg[pos[i]]);puts("");
        }
        printf("%d
    ", ans);
    }
    
    int main(){
        freopen("c.in","r",stdin);
        freopen("c.out","w",stdout);
        scanf("%d%d", &n, &m);
        root = build();
        int siz, lst, now;
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &siz, &lst);
            add(0, ++idx);
            add(idx, pos[lst]);
            for(int j = 2; j <= siz; j++){
                scanf("%d", &now);
                add(idx, pos[now]);
                modify(lst+1, now-1, idx);
                lst = now;
            }
        }
        solve();
    }
    View Code

    第三题:一道巨复杂的费用流,又颓了没听,以下是std

    //2s 512M
    #define PN "trouble"
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    template<class T>inline void readin(T &res) {
        static char ch;T flag = 1;
        while((ch=getchar())<'0'||ch>'9')if(ch=='-')flag=-1;
        res=ch-48;
        while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-48;
        res*=flag;
    }
    template<class T>inline T abs(T a) {return a >= 0? a: -a;}
    template<class T>inline T max(T a,T b) {return a >= b? a: b;}
    template<class T>inline T min(T a,T b) {return a <= b? a: b;}
    
    const int N = 40 + 10;
    const int INF = 0x3f3f3f3f;
    const int NODES = 10 * N * N;
    const int EDGES = 100 * N * N;
    struct EDGE {int v, res, cost, upre;} g[EDGES];
    int head[NODES], ne = 1;
    inline void adde(int u,int v,int cap,int cost) {
        g[++ne] = (EDGE){v,cap,cost,head[u]};head[u] = ne;
        g[++ne] = (EDGE){u,0,-cost,head[v]};head[v] = ne;
    }
    
    int s, t;
    int flow, cost;
    
    #include <queue>
    std::queue<int> q;
    int d[NODES], a[NODES], p[NODES];
    bool inq[NODES];
    bool SPFA() {
        while(!q.empty()) q.pop();
        memset(d,63,sizeof(int)*(t+1));
        memset(inq,false,sizeof(int)*(t+1));
        d[s] = 0;inq[s] = true;q.push(s);
        a[s] = INF;
    
        int u, i, v;
        while(!q.empty()) {
            u = q.front();q.pop();inq[u] = false;
            for( i = head[u]; i; i = g[i].upre ) if(g[i].res && d[v = g[i].v] > d[u] + g[i].cost) {
                d[v] = d[u] + g[i].cost;
                if(!inq[v]) inq[v] = true, q.push(v);
                p[v] = i;a[v] = min(a[u],g[i].res);
            }
        }
        if(d[t] == INF) return false;
        flow += a[t];cost += a[t] * d[t];
        for( u = t; u != s; g[p[u]].res -= a[t], g[p[u]^1].res += a[t], u = g[p[u]^1].v );
        return true;
    }
    
    int T, n, m, A, B, t2, Q;
    bool Ball[N][N];
    inline int HOLE(int x,int y,int z) {return 3 * (x * m + y) + z + 1;}
    int main() {
        freopen(PN".in","r",stdin);
        freopen(PN".out","w",stdout);
        readin(T);//T=8~12 ans>0 print 1
        readin(n);readin(m);readin(A);readin(B);
    
        s = 0;t = 3 * n * m + 2;
        memset(head,0,sizeof(int)*(t+1));ne = 1;
    
        t2 = 3 * n * m + 1;adde(t2,t,0,0);
        for( int i = 0, j; i < n; i++ ) for( j = 0; j < m; j++ ) {
            scanf("%1d",&Ball[i][j]);Ball[i][j] ^= 1;
            if((i+j)&1) {
                adde(s,HOLE(i,j,0),1,0);
                adde(s,HOLE(i,j,0),1,A);
                adde(s,HOLE(i,j,0),1,2*A);
                adde(s,HOLE(i,j,0),1,3*A);
                adde(HOLE(i,j,0),HOLE(i,j,1),1,0);
                adde(HOLE(i,j,0),HOLE(i,j,1),1,B-A);
                adde(HOLE(i,j,0),HOLE(i,j,2),1,0);
                adde(HOLE(i,j,0),HOLE(i,j,2),1,B-A);
            } else {
                adde(HOLE(i,j,0),t2,1,0);
                adde(HOLE(i,j,0),t2,1,A);
                adde(HOLE(i,j,0),t2,1,2*A);
                adde(HOLE(i,j,0),t2,1,3*A);
                adde(HOLE(i,j,1),HOLE(i,j,0),1,0);
                adde(HOLE(i,j,1),HOLE(i,j,0),1,B-A);
                adde(HOLE(i,j,2),HOLE(i,j,0),1,0);
                adde(HOLE(i,j,2),HOLE(i,j,0),1,B-A);
            }
        }
        for( int i = 0, j; i < n; i++ ) for( j = 0; j < m; j++ )
            if(((i+j)&1) && Ball[i][j]) {
                if(j != 0 && Ball[i][j-1])
                    adde(HOLE(i,j,1),HOLE(i,j-1,1),1,0);
                if(j != m - 1 && Ball[i][j+1])
                    adde(HOLE(i,j,1),HOLE(i,j+1,1),1,0);
                if(i != 0 && Ball[i-1][j])
                    adde(HOLE(i,j,2),HOLE(i-1,j,2),1,0);
                if(i != n - 1 && Ball[i+1][j])
                    adde(HOLE(i,j,2),HOLE(i+1,j,2),1,0);
            }
    
        readin(Q);
        for( int x = 1, i; x <= Q; x++ ) {
            for( i = head[t2]; i; i = g[i].upre )
                if(g[i].v == t) g[i].res++;
            while(SPFA());
            printf("%d
    ",8 <= T && T <= 12?cost > 0:cost);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Color Length UVA
    从一个n位数中选出m位按顺序组成新数并使其最大 || Erasing and Winning UVA
    Bits Equalizer UVA
    Party Games UVA
    笔记 树状数组--区间查询+区间修改
    算法竞赛入门经典 笔记(1)
    Database UVA
    set有关的函数的用法(The SetStack Computer UVA
    ndk学习之C语言基础复习----结构体、共用体与C++开端
    ndk学习之C语言基础复习----基本数据类型、数组
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9394250.html
Copyright © 2011-2022 走看看