zoukankan      html  css  js  c++  java
  • 2020/10/4

    两题:

    ///链接:https://www.luogu.com.cn/problem/P2754
    /*题意: n太空站,m飞船,每个飞船有以一固定且循环的航线,每一秒能移动一步,现在问你最起码要多少秒,才能把地球上的
            k个人转移到月球上去。
      题解:首先无解的情况,地球和月球之间没有路线,那么直接输出0;现在要考虑的是有解的情况。
      这里我们需要按照时间进行分层,即第一秒的时候图是怎么样的,跑下最大流,看最大流是否大于等于k。如果是,则直接退出;
      如果不是,则就证明当前时间还不满足,我们就看s+1秒的时候的最大流。直到满足最大流大于等于k。
      按时间建的分层图;有东西。
    */
    #include"stdio.h"
    #include"string.h"
    #include"stack"
    #include"map"
    #include"math.h"
    #include"iostream"
    #include"vector"
    #include"queue"
    #include"algorithm"
    using namespace std;
    #define OK printf("
    ");
    #define Debug printf("this_ok
    ");
    #define INF 1e18
    typedef long long ll;
    #define scanll(a,b) scanf("%lld%lld",&a,&b);
    #define scanl(a) scanf("%lld",&a);
    #define printl(a,b) if(b == 0) printf("%lld ",a); else printf("%lld
    ",a);
    #define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d
    ",a);
    typedef pair<int,int> PII;
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    const ll mod = 998244353;
    const int N = 1000010,M = 1000010;
    const int inf = 1 << 29;
    const int dirx[4] = {-1,0,1,0};
    const int diry[4] = {0,1,0,-1};
    int n,m,t,s,tot;
    ll maxflow,sum;
    int head[N],ver[M],Next[M],edge[M],d[N];
    queue<int> q;
    int w[220],len[220];
    int G[210][210];
    int far[220];
    int ans;
    void add(int x,int y,int z){
        ver[++ tot] = y; Next[tot] = head[x];  edge[tot] = z; head[x] = tot;
        ver[++ tot] = x; edge[tot] = 0; Next[tot] = head[y]; head[y] = tot;
    }
    int Find(int x){
        if(x == far[x]) return x;
        return far[x] = Find(far[x]);
    }
    bool bfs(){
        memset(d,0,sizeof(d));
        while(q.size())q.pop();
        q.push(s); d[s] = 1;
        while(q.size()){
            int x = q.front(); q.pop();
            for(int i = head[x]; i; i = Next[i])
            if(edge[i] && !d[ver[i]]){
                q.push(ver[i]); d[ver[i]] = d[x] + 1;
                if(ver[i] == t) return 1;
            }
        }
        return 0;
    }
    
    int dinic(int x,ll flow){
    
        if(x == t) return flow;
        ll rest = flow,k;
        for(int i = head[x]; i && rest; i = Next[i]){
             if(edge[i] && d[ver[i]] == d[x] + 1){
                k = dinic(ver[i],min(rest,(ll)edge[i]));
                if(!k) d[ver[i]] = 0;
                edge[i] -= k;
                edge[i ^ 1] += k;
                rest -= k;
             }
        }
        return flow - rest;
    }
    int main(){
        //n = read(); m = read();
        int k; // = read();
        scanf("%d%d%d",&n,&m,&k);
        for(int i = 0; i <= 200; i ++) far[i] = i;
        for(int i = 1; i <= m; i ++){
           //w[i] = read();len[i] = read();
           scanf("%d%d",&w[i],&len[i]);
           int fx = 0;
           for(int j = 0; j < len[i]; j ++){
    //          G[i][j] = read();
              scanf("%d",&G[i][j]);
              if(G[i][j] == -1) G[i][j] = n + 2;
              if(G[i][j] == 0) G[i][j] = n + 1;
              if(j == 0) continue;
    
              int fy = Find(G[i][j]);
              int fx = Find(G[i][j - 1]);
              if(fx != fy) far[fx] = fy;
    
           }
        }
        if(Find(n + 1) != Find(n + 2))
        {printf("0
    "); return 0;}
    
        ///地球n+1,月球n+2 起点n+3,源点n+4
        s = 0; t = 999;
        int eq = n + 1,mq = n + 2;
        tot = 1;
        ans = 0; int tt = n + 2;
        while(ans >= 0){
            add(s,ans * tt + eq,inf);
            add(ans * tt + mq,t,inf);
            if(ans != 0){
                for(int i = 1; i <= n + 2; i ++)
                    add((ans - 1) * tt + i,ans * tt + i,inf);
                for(int i = 1; i <= m; i ++){
                    int x = G[i][(ans - 1)%len[i]];
                    int y = G[i][ans%len[i]];
                    add((ans - 1) * tt + x,ans * tt + y,w[i]);
                    //printf("i = %d m = %d
    ",i,m);
                }//printf("ok");
            }
            ll flow = 0,s1 = 0;
            while(bfs())
              while(flow = dinic(s,inf)) s1 += flow;
            sum += s1;
            if(sum >= k) break;
            ans ++;
           // printf("ans = %d
    ",ans);
        }
        //if(ans == 101) printf("0
    ");
         printf("%d
    ",ans);
    }
    /*
    3
    1 2 3
    2
    2 6
    */
    ///链接:https://ac.nowcoder.com/acm/contest/7831/H
    /*题意:n结点树,每个结点有一颜色,两种操作,1,查询包含所有x颜色的结点最起码要多少条边
            2,修改v顶点颜色改为x;
      题解:对每种颜色的点用一个set来存,set的排序规则按照dfs序,能发现每修改一个点的颜色
      对该颜色的答案的贡献只和其在set中前后的两个点l,r有关,set中增加一个点x对答案的贡献为
      dis(l,x)+dis(x,r)−dis(l,r),删除一个点对答案的贡献为dis(l,r)−dis(l,x)−dis(x,r),能发
      现这样得到的每个颜色的答案再加上set中第一个点start和最后一个点end之间的距离
      dis(start,end)刚好是正确答案的两倍。对与每个询问答案的操作输出(ans[i]+dis(start,end))/2。
    */
    
    #include <iostream>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cctype>
    #include <queue>
    #include <stdlib.h>
    #include <cstdlib>
    #include <math.h>
    #include <set>
    #include"queue"
    #include <vector>
    #define inf 107374182
    #define M 10010001
    #define ll long long
    #define PII pair<int,int>
    using namespace std;
    inline int read(){
        int s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9')   { if(ch == '-') w = -1; ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
        return s * w;
    }
    
    const int N = 2001000;
    int head[N],ver[N << 1],Next[N << 1],tot;
    int n,m,a[N],dfn[N],top;
    int f[N][22],d[N],dist[N],t;
    int ans[N];
    queue<int> q;
    struct cmp{
        bool operator()(const int &x,const int &y) const {
            return dfn[x] < dfn[y];
        }
    };
    set<int,cmp> G[N];
    
    void add(int x,int y){
        ver[++ tot] = y; Next[tot] = head[x]; head[x] = tot;
    }
    
    void bfs(){
        q.push(1); d[1] = 1;
        while(q.size()){
            int x = q.front(); q.pop();
            for(int i = head[x]; i; i = Next[i]){
                int y = ver[i];
                if(d[y]) continue;
                d[y] = d[x] + 1;
                dist[y] = dist[x] + 1;
                f[y][0] = x;
                for(int j = 1; j <= t; j ++)
                    f[y][j] = f[f[y][j - 1]][j - 1];
                q.push(y);
            }
        }
    }
    int lca(int x,int y){
        if(d[x] > d[y]) swap(x,y);
        for(int i = t; i >= 0;i --)
            if(d[f[y][i]] >= d[x]) y = f[y][i];
        if(x == y) return x;
        for(int i = t; i >= 0;i --)
            if(f[x][i] != f[y][i]) x = f[x][i],y = f[y][i];
        return f[x][0];
    }
    int dis(int x,int y){
        return d[x]+d[y]-2*d[lca(x,y)];
    }
    void dfs(int x,int f){
        dfn[x] = ++ top;
        for(int i = head[x]; i; i = Next[i]){
            int y = ver[i];
            if(y == f) continue;
            dfs(y,x);
        }
    }
    void Add(int x){
        G[a[x]].insert(x);
        auto it = G[a[x]].find(x);
        int l = 0,r = 0;
        ++ it;
        if(it != G[a[x]].end()){
            r = *it;
        }
        -- it;
        if(it != G[a[x]].begin()){
            -- it;
            l = *it;
        }
        if(l && r) ans[a[x]] -= dis(l,r);
        if(l) ans[a[x]] += dis(l,x);
        if(r) ans[a[x]] += dis(x,r);
    }
    void Del(int x){
        auto it = G[a[x]].find(x);
        int l = 0,r = 0;
        ++ it;
        if(it != G[a[x]].end()) r = *it;
        -- it;
        if(it != G[a[x]].begin()){
            -- it;
            l = *it;
        }
        if(l && r) ans[a[x]] += dis(l,r);
        if(l) ans[a[x]] -= dis(l,x);
        if(r) ans[a[x]] -= dis(x,r);
        G[a[x]].erase(x);
    }
    int main(){
        n = read(); t = (int)(log(n)/log(2)) + 1;
        for(int i = 2;i <= n; i ++){
            int x = read(),y = read();
            add(x,y); add(y,x);
        }
        bfs();dfs(1,0);
        for(int i = 1; i <= n; i ++) {
            a[i] = read();
            Add(i);
        }
        m = read();
        while(m --){
            char str[2]; scanf("%s",str);
            if(str[0] == 'Q') {
                int x = read();
                if(G[x].empty()) printf("-1
    ");
                else if(G[x].size() == 1) printf("%d
    ",ans[x]);
                else printf("%d
    ",(ans[x] + dis(*G[x].begin(),*G[x].rbegin()))/2);
            } else {
                int x = read(),y = read();
                Del(x);a[x] = y;
                Add(x);
            }
        }
    }
  • 相关阅读:
    Android Studio下载及离线升级方法
    动态调用WebService
    哈哈哈 终于通过自己的努力 把这个模板上长毛的土豆去掉了
    关于“只有注册用户登录后才能阅读该文”
    SQL Server 2008 R2——根据数据查找表名和字段名 根据脏数据定位表和字段
    Windows驱动——虚拟机 虚拟串口 双机调试
    协议——如何制作一个简易的串口通信协议
    问题解决——复合检测项目的定义和使用
    算法——成语首尾接龙 成语接龙
    C++基础——函数指针 函数指针数组
  • 原文地址:https://www.cnblogs.com/yrz001030/p/13768515.html
Copyright © 2011-2022 走看看