zoukankan      html  css  js  c++  java
  • 51nod1331 狭窄的通道

     题目传送门

    这道题 51nod只Ac了十二个人 没有题解可以研究 所以就自己YY了半天 在这里先感谢一波岚清大爷 orz 

    然后这道题我分了两种情况 一种是左边的往左跑右边的往右跑 中间有一部分直接走不用跑左右

    另一种是全部都要跑左右 然后有一部分点需要左右都跑的 但是左跑和右跑的有一部分点会相互冲突 这个时候需要处理一波矛盾关系 

    讲的不清楚 给一份数据自己模拟试试吧(再次感谢一波 orzllq)

      1
      5 11
      5 3
      3 4
      1 10
      7 9
      9 1

    这个时候 我们第一个想到的是一波网络流找最小割 经过一波混乱以后 代码成功出世并且意外AC了 贴一波代码

    当然也可以贪心枚举而且数据大了会快很多 推荐一篇写的很全的博客吧 orzzsn

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<cstdlib>
    #define LL long long
    using namespace std;
    const int M=105,inf=0x3f3f3f3f;
    LL read(){
        LL ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    LL ans,sum,cnt;
    LL n,L,m,S,T;
    int f[M][M];
    struct node{LL l,r;}e[2*M];
    bool cmp(node a,node b){return a.l<b.l;}
    int first[M],cur[M];
    struct note{LL to,next,flow;}q[2*M*M];
    void ins(LL a,LL b,LL flow){cnt++; q[cnt].to=b; q[cnt].flow=flow; q[cnt].next=first[a]; first[a]=cnt;}
    void insert(int a,int b,int flow){ins(a,b,flow); ins(b,a,0);}
    void find1(LL x,LL k){
        bool f=0;
        LL now=e[x].r;
        for(int i=k+1;i<=n;i++) if(now>e[i].r) insert(x,i,inf),f=1;
        if(f) insert(S,x,2*(L-e[x].r));
    }
    void find2(LL x,LL k){
        LL now=e[x].r;
        for(int i=1;i<=k;i++) if(now<e[i].r){
            insert(x,T,2*e[x].r);
            break;
        }
    }
    int check(int x){
        LL mx1=0,mx2=L,now=e[x].r;
        for(int i=1;i<x;i++) mx1=max(mx1,e[i].r);
        for(int i=x+1;i<=n;i++) mx2=min(mx2,e[i].r);
        return mx1<now&&mx2>now;
    }
    int okay(int x){
        LL mx1=0,mn1=L;
        for(int i=1;i<=x;i++) mx1=max(mx1,e[i].r);
        for(int i=x+1;i<=n;i++) mn1=min(mn1,e[i].r);
        return mx1<mn1;
    }
    LL calc1(int x){
        LL sum=0;
        for(int i=1;i<=x;i++) sum=sum+e[i].l+e[i].r;
        return sum;
    }
    LL calc2(int x){
        LL sum=0;
        for(int i=x;i<=n;i++) sum=sum+(2*L-e[i].l-e[i].r);
        return sum;
    }
    LL pd(LL x){return x>=0?x:-x;}
    LL d[M],st[M];
    int bfs(){
        memset(d,-1,sizeof(d));
        int head=0,tail=1;
        st[0]=S; d[S]=0;
        while(head!=tail){
            int x=st[head++]; if(head>M) head=0;
            for(int i=first[x];i;i=q[i].next){
                int now=q[i].to;
                if(q[i].flow&&d[now]==-1){st[tail++]=now; d[now]=d[x]+1; if(tail>M) tail=0;}
            }
        }
        return d[T]!=-1;
    }
    LL dfs(LL x,LL a){
        if(x==T||a==0) return a;
        int f,flow=0;
        for(int &i=cur[x];i;i=q[i].next){
            int now=q[i].to;
            if(d[now]==d[x]+1&&(f=dfs(now,min(a,q[i].flow)))>0){
                q[i].flow-=f; q[i^1].flow+=f;
                flow+=f;
                a-=f; if(a==0) break;
            }
        }
        return flow;
    }
    LL dinic(){
        LL ans=0;
        while(bfs()){for(int i=0;i<=T;i++) cur[i]=first[i]; ans+=dfs(S,inf);}
        return ans; 
    }
    int main()
    {
        for(int v=read();v;v--){
            ans=inf; n=read(); L=read();
            for(int i=1;i<=n;i++) e[i].l=read(),e[i].r=read();
            e[0].l=0; e[0].r=0; e[n+1].l=L; e[n+1].r=L;
            sort(e+1,e+1+n,cmp);
            sum=0; for(int i=1;i<=n;i++) sum=sum+e[i].l+e[i].r; ans=min(ans,sum);
            sum=0; for(int i=1;i<=n;i++) sum=sum+(2*L-e[i].r-e[i].l); ans=min(ans,sum);
            for(int i=0;i<=n;i++)if(okay(i)){
                int k=i+1; sum=0;
                sum+=calc1(i);
                while(check(k)) sum=sum+pd(e[k].r-e[k].l),k++;
                sum+=calc2(k);
                ans=min(ans,sum);
            }
            for(int i=1;i<=n;i++){
                sum=0; cnt=1; S=0; T=n+1;
                memset(first,0,sizeof(first));
                sum+=calc1(i)+calc2(i+1); 
                for(int k=1;k<=i;k++) find1(k,i);
                for(int k=i+1;k<=n;k++) find2(k,i);
                sum+=dinic();
                ans=min(ans,sum);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Func<T>、Action<T> 的区别于说明
    Invoke()/BeginInvoke()区别
    C# Linq处理list数据
    C# 的三种序列化方法
    P3368 【模板】树状数组 2
    P2058 海港
    2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解
    2019.6.20 校内测试 NOIP模拟 Day 1 分析+题解
    2019.6.18 校内测试 分析+题解
    P1310 表达式的值
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7116398.html
Copyright © 2011-2022 走看看