zoukankan      html  css  js  c++  java
  • BestCoder Round #74

    身败名裂啊。。。。。。

    T1WA了半天,30min才A。

    T2又WA了一发,然后Hack刚2min就被别人叉了。

    T3做完后最后40min不知所措。

    去叉别人,看到一个人写D题判m=0很奇怪,随手把他叉了:

    1

    3 0

    然后发现,标程输出1.

    奥妙重重

    嘿嘿嘿,我竟然又去叉了吉利。

    T1的SB错误是,答案可能是|x-y|。

    T2的SB错误是,一个[1,10^5]的数异或[1,10^5]的数可能是[1,131072]的数。

    T1 Shortest Path

    x到y的路径可能有几种:
    1.x->y

    2.x->i->j>y

    其中i和j是新边里的节点(称为关键节点)

    将六个关键点连起来跑一下Floyd,然后每次询问时枚举一下i,j。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<map>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=100010;
    int n,m,u[5],v[5],A[10],cnt;
    int W[10][10];
    map<int,int> M;
    int find(int x) {
        if(!M.count(x)) M[x]=++cnt,A[cnt]=x;
        return M[x];
    }
    const int mod=1000000007;
    int main() {
        dwn(T,read(),1) {
            n=read();m=read();M.clear();cnt=0;
            rep(i,1,6) rep(j,1,6) W[i][j]=100000000;
            rep(i,1,6) W[i][i]=0;
            rep(i,1,3) u[i]=read(),v[i]=read(),W[find(u[i])][find(v[i])]=W[find(v[i])][find(u[i])]=1;
            rep(i,1,cnt) rep(j,1,cnt) W[i][j]=min(W[i][j],abs(A[i]-A[j]));
            rep(k,1,cnt) rep(i,1,cnt) rep(j,1,cnt) W[i][j]=min(W[i][j],W[i][k]+W[k][j]);
            long long res=0;
            rep(i,1,m) {
                int x=read(),y=read(),ans=abs(x-y);
                rep(k,1,cnt) rep(j,1,cnt) ans=min(ans,abs(A[k]-x)+abs(A[j]-y)+W[k][j]);
                (res+=(long long)i*ans)%=mod;
            }
            printf("%I64d
    ",res);
        }
        return 0;
    }
    View Code

    T2 Transform

    x -> y  <=> 0 -> x xor y

    所以从0BFS一下就好了。

    然后应该搜到[1,131072]。QAQ(AQ)*

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=300010;
    const int mod=1000000007;
    typedef long long ll;
    int n,m,A[maxn],vis[maxn],d[maxn];
    queue<int> Q;
    void bfs() {
        memset(vis,0,sizeof(vis));d[0]=0;vis[0]=1;Q.push(0);
        while(!Q.empty()) {
            int x=Q.front();Q.pop();
            rep(i,0,20) {
                int v=x^(1<<i);
                if(v<=300000&&!vis[v]) {
                    vis[v]=1;d[v]=d[x]+1;Q.push(v);
                }
            }
            rep(i,1,n) {
                int v=x^A[i];
                if(v<=300000&&!vis[v]) {
                    vis[v]=1;d[v]=d[x]+1;Q.push(v);
                }
            }
        }
    }
    int main() {
        dwn(T,read(),1) {
            n=read();m=read();
            rep(i,1,n) A[i]=read();
            bfs();ll ans=0;
            rep(i,1,m) (ans+=(ll)i*d[read()^read()])%=mod;
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code

    T3 Toposort

    我们逐位考虑,那么我们需要一个数据结构完成这样的功能。

    1.找到当前权值<=k的最小节点。

    2.将一个节点的权值-1。

    显然线段树就行了。

    我懒得写线段树,于是STL大法好。

    用一个堆来维护一下在某次操作前权值<=k的节点,不行就把它踢出去。

    然后拓扑的时候再判判能不能扔到堆里。

    因为最多有n+m个节点进入堆,所以时间复杂度为O((n+m)logn)。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<queue>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    using namespace std;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int mod=1000000007;
    const int maxn=100010;
    const int maxm=200010;
    typedef long long ll;
    int n,m,k,first[maxn],Next[maxm],to[maxm],in[maxn],is[maxn],e;
    void AddEdge(int u,int v) {
        to[++e]=v;Next[e]=first[u];first[u]=e;in[v]++;
    }
    int main() {
        dwn(T,read(),1) {
            n=read();m=read();k=read();
            rep(i,1,n) in[i]=first[i]=is[i]=0;e=0;
            rep(i,1,m) {
                int u=read(),v=read();
                AddEdge(u,v);
            }
            priority_queue<int> Q;
            rep(i,1,n) if(in[i]<=k) is[i]=1,Q.push(-i);
            ll ans=0;
            rep(j,1,n) {
                int x;
                while(Q.size()) {
                    x=-Q.top();Q.pop();is[x]=0;
                    if(in[x]<=k) break;
                }
                (ans+=(ll)j*x)%=mod;k-=in[x];in[x]=0;is[x]=1;
                for(int i=first[x];i;i=Next[i]) if(in[to[i]]) {
                    in[to[i]]--;
                    if(in[to[i]]<=k&&!is[to[i]]) is[to[i]]=1,Q.push(-to[i]);
                }
            }
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code

    T4 Deletion

    比赛时并没有想出来QAQ(AQ)*

    这道题想法很妙,考虑题目说的“要求选出来的边构成的子图的每个连通块最多只有一个环”其实就是环套树。

    而如果对一个无向图进行定向,满足所有节点的出边最多只有1,那么这个无向图可以一次选出。

    所以问题转化成对一个无向图进行定向,让出边最多的节点出度最少,那么二分答案后就是一个分配模型了。

    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i!=-1;i=Next[i])
    using namespace std;
    typedef long long ll;
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int maxn=5010;
    const int maxm=100010;
    const int inf=1e9;
    struct Dinic {
        int n,m,s,t,first[maxn],Next[maxm];
        void init(int n) {
            m=0;this->n=n;
            memset(first,-1,sizeof(first));
        }
        struct Edge {int from,to,flow;}edges[maxm];
        void AddEdge(int u,int v,int w) {
            edges[m]=(Edge){u,v,w};Next[m]=first[u];first[u]=m++;
            edges[m]=(Edge){v,u,0};Next[m]=first[v];first[v]=m++;
        }
        int d[maxn],vis[maxn],cur[maxn];
        int BFS() {
            memset(vis,0,sizeof(vis));
            queue<int> Q;Q.push(s);vis[s]=1;
            while(!Q.empty()) {
                int x=Q.front();Q.pop();cur[x]=first[x];
                ren {
                    Edge& e=edges[i];
                    if(!vis[e.to]&&e.flow) {
                        vis[e.to]=1;
                        d[e.to]=d[x]+1;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
        int DFS(int x,int a) {
            if(x==t||!a) return a;
            int flow=0,f;
            for(int& i=cur[x];i!=-1;i=Next[i]) {
                Edge& e=edges[i];
                if(d[e.to]==d[x]+1&&(f=DFS(e.to,min(a,e.flow)))) {
                    e.flow-=f;edges[i^1].flow+=f;
                    a-=f;flow+=f;if(!a) break;
                }
            }
            return flow;
        }
        int solve(int s,int t) {
            this->s=s;this->t=t;int flow=0;
            while(BFS()) flow+=DFS(s,inf);
            return flow;
        }
    }sol;
    int n,m,u[maxn],v[maxn];
    int check(int x) {
        int s=n+m+1,t=n+m+2;sol.init(t);
        rep(i,1,n) sol.AddEdge(s,i,x);
        rep(i,1,m) sol.AddEdge(i+n,t,1);
        rep(i,1,m) sol.AddEdge(u[i],i+n,1),sol.AddEdge(v[i],i+n,1);
        return sol.solve(s,t)==m;
    }
    void solve() {
        n=read();m=read();
        rep(i,1,m) u[i]=read(),v[i]=read();
        if(!m) {puts("0");return;}
        int l=1,r=m,mid;
        while(l<r) if(check(mid=l+r>>1)) r=mid; else l=mid+1;
        printf("%d
    ",l);
    }
    int main() {
        dwn(T,read(),1) solve();
        return 0;
    }
    View Code
  • 相关阅读:
    Atitti 图像处理 图像混合 图像叠加 blend 原理与实现
    Atitit Gaussian Blur 高斯模糊 的原理and实现and 用途
    Atitit 图像处理 灰度图片 灰度化的原理与实现
    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结
    Atitit 实现java的linq 以及与stream api的比较
    Atitit attilax在自然语言处理领域的成果
    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库
    Atitit 图像处理--图像分类 模式识别 肤色检测识别原理 与attilax的实践总结
    Atitit apache 和guava的反射工具
    atitit。企业的价值观 员工第一 vs 客户第一.docx
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5248571.html
Copyright © 2011-2022 走看看