zoukankan      html  css  js  c++  java
  • 2019 HL SC day2

      今天讲的是网络流 大部分题目都写过了 这里 就总结一番。

    bzoj 1066 裸的最大流 不过需要拆点细节方面有一点坑 剩下的 没什么了。

     //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<cmath>
    #include<algorithm>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<queue>
    #include<stack>
    #include<deque>
    #include<map>
    #include<vector>
    #include<ctime>
    #define ll long long
    #define INF 1000000000
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin)),fs==ft)?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=150010,maxn=30;
    int n,m,h,t,S,T,c,maxflow,cnt,num,len=1;
    int q[MAXN],vis[MAXN];
    char a[maxn][maxn],b[maxn][maxn];
    int pos[maxn][maxn],dis[maxn][maxn];
    int lin[MAXN],nex[MAXN],ver[MAXN],e[MAXN];
    int dx[5]={0,0,0,1,-1};
    int dy[5]={0,1,-1,0,0};
    inline void add(int x,int y,int z)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
    }
    inline void bfs(int x,int y)
    {
        memset(dis,0,sizeof(dis));
        h=t=0;q[++t]=x;vis[t]=y;
        //cout<<x<<' '<<y<<endl;
        while(h++<t)
        {
            for(int i=1;i<=4;++i)
            {
                int xx=q[h]+dx[i];
                int yy=vis[h]+dy[i];
                if(xx<0||yy<0||xx>n||yy>m)continue;
                if(xx==x&&yy==y)continue;
                if(dis[xx][yy])continue;
                dis[xx][yy]=dis[q[h]][vis[h]]+1;
                if(dis[xx][yy]>c)continue;
                if(a[xx][yy]!='0')add(pos[x][y]+num,pos[xx][yy],INF);
                q[++t]=xx;vis[t]=yy;
            }
        }
        if(min(x,y)<=c||min((n-x+1),(m-y+1))<=c)
        {
            //cout<<x<<' '<<y<<endl;
            add(pos[x][y]+num,T,INF);
        }
    }
    inline int bfs()
    {
        memset(vis,0,sizeof(vis));
        h=t=0;q[++t]=S;vis[S]=1;
        while(h++<t)
        {
            int x=q[h];
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(!e[i]||vis[tn])continue;
                vis[tn]=vis[x]+1;
                q[++t]=tn;
                if(tn==T)return 1;
            }
        }
        return 0;
    }
    inline int dinic(int x,int flow)
    {
        if(x==T)return flow;
        int rest=flow,k;
        for(int i=lin[x];i&&rest;i=nex[i])
        {
            int tn=ver[i];
            if(e[i]&&vis[tn]==vis[x]+1)
            {
                k=dinic(tn,min(e[i],rest));
                if(!k)vis[tn]=0;
                e[i]-=k;e[i^1]+=k;
                rest-=k;
            }
        }
        return flow-rest;
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();c=read();
        for(int i=1;i<=n;++i)scanf("%s",a[i]+1);
        for(int i=1;i<=n;++i)scanf("%s",b[i]+1);
        S=n*m*3+1;T=S+1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                pos[i][j]=++num;
                if(b[i][j]!='L')continue;
                ++cnt;add(S,cnt+n*m*2,1);
                add(cnt+n*m*2,pos[i][j],1);
            }
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=m;++j)
                if(a[i][j]!='0')
                {
                    add(pos[i][j],pos[i][j]+num,a[i][j]-'0');
                    bfs(i,j);
                }
        }
        int flow=0;while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
        printf("%d
    ",cnt-maxflow);
        return 0;
    }
    View Code

    bzoj 3993 最大流 需要二分一下答案 然后最大流分配攻击 看能否全部攻击。有点小卡精度 需要*10000 实数上二分较好。

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<queue>
    #include<iomanip>
    #include<cctype>
    #include<cstdio>
    #include<deque>
    #include<utility>
    #include<cmath>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    #include<stack>
    #include<map>
    #include<set>
    #include<bitset>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    #define INF 1000000000
    #define ll long long
    #define RE register
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=55,maxn=100010;
    int n,m,len=1,S,T,h,t;
    int c[MAXN][MAXN],flag[MAXN];
    int lin[maxn],nex[maxn],ver[maxn],vis[maxn],q[maxn];
    ll e[maxn],a[MAXN],b[MAXN],ti,sum;
    inline void add(int x,int y,ll z)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
    }
    inline int bfs()
    {
        memset(vis,0,sizeof(vis));
        h=t=0;q[++t]=S;vis[S]=1;
        while(h++<t)
        {
            int x=q[h];
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(!e[i]||vis[tn])continue;
                vis[tn]=vis[x]+1;
                q[++t]=tn;
                if(tn==T)return 1;
            }
        }
        return 0;
    }
    inline ll dinic(int x,ll flow)
    {
        if(x==T)return flow;
        ll rest=flow,k;
        for(int i=lin[x];i&&rest;i=nex[i])
        {
            int tn=ver[i];
            if(e[i]&&vis[tn]==vis[x]+1)
            {
                k=dinic(tn,min(e[i],rest));
                if(!k)vis[tn]=0;
                e[i]-=k;e[i^1]+=k;
                rest-=k;
            }
        }
        return flow-rest;
    }
    inline int check()
    {
        ll flow=0,maxflow=0;
        while(bfs())while((flow=dinic(S,INF*10000ll)))maxflow+=flow;
        return maxflow==sum;
    }
    inline void build(ll x)
    {
        len=1;memset(lin,0,sizeof(lin));
        for(int i=1;i<=m;++i)add(S,i,x*b[i]);
        for(int i=1;i<=n;++i)add(i+m,T,a[i]);
        for(int i=1;i<=m;++i)
            for(int j=1;j<=n;++j)
                if(c[i][j])add(i,j+m,INF*10000ll);
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();
        S=n+m+1;T=S+1;
        for(int i=1;i<=n;++i)a[i]=read()*10000ll,sum+=a[i];
        for(int i=1;i<=m;++i)b[i]=read();
        for(int i=1;i<=m;++i)
            for(int j=1;j<=n;++j)
            {
                c[i][j]=read();
                if(c[i][j]&&!flag[j])ti+=a[j],flag[j]=1;
            }
        ll l=0,r=ti;
        while(l+1<r)
        {
            ll mid=(l+r)>>1;
            build(mid);
            if(check())r=mid;
            else l=mid;
        }
        build(l);
        if(check())printf("%.4lf",(double)l/10000.0);
        else printf("%.4lf",(double)r/10000.0);
        return 0;
    }
    View Code

    luogu 4126 很难的最小割问题。竟然还需要tarjan 。。我有点蠢迷了将近20min 才发现一些性质被我完美的忽略掉了。

    1 跑一边最大流 不满流的边一定不会属于割集 显然 我们将其割掉 那么再割掉其他边 那么最小割将>最大流故 不满流的边一定不会属于割集

    2 满流的边有可能属于 割集 有可能也不属于割集 因为存在 流光往一处流的可能。。

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<queue>
    #include<iomanip>
    #include<cctype>
    #include<cstdio>
    #include<deque>
    #include<utility>
    #include<cmath>
    #include<ctime>
    #include<cstring>
    #include<string>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    #include<stack>
    #include<map>
    #include<set>
    #include<bitset>
    #define max(x,y) ((x)>(y)?(x):(y))
    #define min(x,y) ((x)>(y)?(y):(x))
    #define INF 1000000000
    #define ll long long
    #define RE register
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    const int MAXN=4010,maxn=60010<<1;
    int n,m,len=1,S,T,maxflow,t,h,num,cnt,top;
    int q[MAXN],vis[MAXN],dfn[MAXN],low[MAXN],c[MAXN],s[MAXN];
    int lin[MAXN],nex[maxn],ver[maxn],e[maxn];
    inline void add(int x,int y,int z)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
    }
    struct wy
    {
        int x,y,id;
    }w[maxn];
    inline int bfs()
    {
        memset(vis,0,sizeof(vis));
        h=t=0;q[++t]=S;vis[S]=1;
        while(h++<t)
        {
            int x=q[h];
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(!e[i]||vis[tn])continue;
                q[++t]=tn;vis[tn]=vis[x]+1;
                if(tn==T)return 1;
            }
        }
        return 0;
    }
    inline int dinic(int x,int flow)
    {
        if(x==T)return flow;
        int rest=flow,k;
        for(int i=lin[x];i&&rest;i=nex[i])
        {
            int tn=ver[i];
            if(vis[tn]==vis[x]+1&&e[i])
            {
                k=dinic(tn,min(e[i],rest));
                if(!k){vis[tn]=0;continue;}
                e[i]-=k;e[i^1]+=k;rest-=k;
            }
        }
        return flow-rest;
    }
    inline void tarjan(int x)
    {
        dfn[x]=low[x]=++num;
        s[++top]=x;vis[x]=1;
        for(int i=lin[x];i;i=nex[i])
        {
            int tn=ver[i];
            if(e[i]==0)continue;
            if(!dfn[tn])
            {
                tarjan(tn);
                low[x]=min(low[x],low[tn]);
            }
            else if(vis[tn])low[x]=min(low[x],dfn[tn]);
        }
        if(dfn[x]==low[x])
        {
            ++cnt;int y;
            do
            {
                y=s[top--];
                vis[y]=0;
                c[y]=cnt;
            }while(x!=y);
        }
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();S=read();T=read();
        for(int i=1;i<=m;++i)
        {
            int x,y,z;
            x=read();y=read();z=read();
            add(x,y,z);
            w[i]=(wy){x,y,len-1};
        }
        int flow=0;
        while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
        //printf("%d
    ",maxflow);
        //problem 1:是否存在一个最小割的切断方案该道路属于割集
        //problem 2:当前路径是否在任意一个割集中都存在
        //对于问题2 显然的是如果一定是割集的话意味着流入量比当前容量大 可流出量也比当前容量大+1则增大流量
        //那么这条边的左端点一定是和S属于同一个强连通分量之中 右端点和T在同一个强联通分量当中
        //对于问题1 显然暴力可以判断 当然两端如果还能互相到达 那么一定不会属于割集 
        //证明:设这条边左断点为u 右端点为v 且当前满流 v通过反向边一定可以到u u能到v当且仅当从u出发能到T
        //故切掉这条边还有流能到T 若此边属于此割集 就一定不存在这样的流 所以假设不成立。
        //得证。
        for(int i=1;i<=n;++i)if(!dfn[i])tarjan(i);
        for(int i=1;i<=m;++i)
        {
            if(e[w[i].id])printf("%d %d
    ",0,0);
            else 
            {
                if(c[w[i].x]!=c[w[i].y])
                {
                    printf("%d ",1);
                    //cout<<c[w[i].x]<<' '<<c[S]<<endl;
                    //cout<<c[w[i].y]<<' '<<c[T]<<endl;
                    if(c[w[i].x]==c[S]&&c[w[i].y]==c[T])printf("%d
    ",1);
                    else printf("%d
    ",0);
                }
                else printf("%d %d
    ",0,0);
            }
        }
        return 0;
    }
    View Code

    具体怎么写见代码注释。

    bzoj 3894 文理分科 最小割裸题 虚建几个点即可。

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define INF 1000000000
    #define ll long long
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define RI register ll
    #define db double
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    inline void put(int x)
    {
        x<0?x=-x,putchar('-'):0;
        int num=0;char ch[20];
        while(x)ch[++num]=x%10+'0',x/=10;
        num==0?putchar('0'):0;
        while(num)putchar(ch[num--]);
        putchar('
    ');return;
    }
    const int MAXN=110,maxn=400010;
    int n,m,len=1,maxflow,S,T,t,h,sum,cnt;
    int pos[MAXN][MAXN];
    int vis[maxn],q[maxn];
    int lin[maxn],ver[maxn],nex[maxn],e[maxn];
    const int dx[5]={0,0,0,1,-1};
    const int dy[5]={0,1,-1,0,0};
    inline void add(int x,int y,int z)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
    }
    inline int bfs()
    {
        memset(vis,0,sizeof(vis));
        h=t=0;q[++t]=S;vis[S]=1;
        while(h++<t)
        {
            int x=q[h];
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(!e[i]||vis[tn])continue;
                vis[tn]=vis[x]+1;
                q[++t]=tn;
                if(tn==T)return 1;
            }
        }
        return 0;
    }
    inline int dinic(int x,int flow)
    {
        if(x==T)return flow;
        int rest=flow,k;
        for(int i=lin[x];i&&rest;i=nex[i])
        {
            int tn=ver[i];
            if(e[i]&&vis[tn]==vis[x]+1)
            {
                k=dinic(tn,min(e[i],rest));
                if(!k)vis[tn]=0;
                e[i]-=k;e[i^1]+=k;
                rest-=k;
            }
        }
        return flow-rest;
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();
        S=n*m+1;T=S+1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                int x;
                x=read();sum+=x;
                pos[i][j]=++cnt;
                add(S,pos[i][j],x);
            }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                int x=read();sum+=x;
                add(pos[i][j],T,x);
            }
        cnt=T;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                int x=read();
                add(S,++cnt,x);sum+=x;
                for(int k=0;k<5;++k)
                {
                    int xx=i+dx[k];
                    int yy=j+dy[k];
                    if(pos[xx][yy])add(cnt,pos[xx][yy],INF);
                }
            }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)
            {
                int x=read();
                add(++cnt,T,x);sum+=x;
                for(int k=0;k<5;++k)
                {
                    int xx=i+dx[k];
                    int yy=j+dy[k];
                    if(pos[xx][yy])add(pos[xx][yy],cnt,INF);
                }
            }
        int flow=0;while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
        printf("%d
    ",sum-maxflow);
        return 0;
    }
    View Code

    luogu 3749 最大权闭合子图 我很迷的写完了。

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define INF 1000000000
    #define ll long long
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define RI register ll
    #define db double
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    inline void put(int x)
    {
        x<0?x=-x,putchar('-'):0;
        int num=0;char ch[20];
        while(x)ch[++num]=x%10+'0',x/=10;
        num==0?putchar('0'):0;
        while(num)putchar(ch[num--]);
        putchar('
    ');return;
    }
    const int MAXN=110,maxn=MAXN*MAXN<<3;
    int n,m,cnt,t,h,S,T,maxflow,sum,len=1;
    int a[MAXN][MAXN],pos[MAXN][MAXN];
    int b[MAXN],vis[maxn],q[maxn];
    int lin[maxn],ver[maxn],nex[maxn],e[maxn];
    inline void add(int x,int y,int z)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
    }
    inline int bfs()
    {
        memset(vis,0,sizeof(vis));
        h=t=0;q[++t]=S;vis[S]=1;
        while(h++<t)
        {
            int x=q[h];
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(!e[i]||vis[tn])continue;
                q[++t]=tn;vis[tn]=vis[x]+1;
                if(tn==T)return 1;
            }
        }
        return 0;
    }
    inline int dinic(int x,int flow)
    {
        if(x==T)return flow;
        int rest=flow,k;
        for(int i=lin[x];i&&rest;i=nex[i])
        {
            int tn=ver[i];
            if(vis[tn]==vis[x]+1&&e[i])
            {
                k=dinic(tn,min(e[i],rest));
                if(!k){vis[tn]=0;continue;}
                e[i]-=k;e[i^1]+=k;rest-=k;
            }
        }
        return flow-rest;
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();
        for(int i=1;i<=n;++i)b[i]=read();
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j)a[i][j]=read(),pos[i][j]=++cnt;
        S=cnt+1;T=S+1;cnt=T;
        for(int i=1;i<=n;++i)
            for(int j=i;j<=n;++j)
            {
                if(i==j)
                {
                    a[i][j]-=b[i];
                    if(a[i][j]<0)add(pos[i][j],T,-a[i][j]);
                    else add(S,pos[i][j],a[i][j]),sum+=a[i][j];
                    continue;
                }
                if(a[i][j]<0)
                {
                    add(pos[i][j],T,-a[i][j]);
                    add(pos[i][j],pos[i+1][j],INF);
                    add(pos[i][j],pos[i][j-1],INF);
                }
                else
                {
                    sum+=a[i][j];
                    add(S,pos[i][j],a[i][j]);
                    add(pos[i][j],pos[i+1][j],INF);
                    add(pos[i][j],pos[i][j-1],INF);
                }
            }
        for(int i=1;i<=n;++i)
        {
            if(!vis[b[i]])
            {
                vis[b[i]]=++cnt;
                add(vis[b[i]],T,m*b[i]*b[i]);
            }
            add(pos[i][i],vis[b[i]],INF);
            //cout<<pos[i][i]<<' '<<vis[b[i]]<<endl;
        }
        int flow=0;
        while(bfs())while((flow=dinic(S,INF)))maxflow+=flow;
        printf("%d
    ",max(0,sum-maxflow));
        return 0;
    }
    View Code

    迷的地方在这里 如果一个组合权值为负 那么是这样连边:

    而并非这样:

    理由是 我选择了 l r 必须选择 l+1,r 和 r-1,l 这是必要的 第二种连边体现不出来这个特点故是错误的。

    最大密度子图 01分数规划后转 最大权闭合子图即可。

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define INF 1000000000
    #define ll long long
    #define min(x,y) ((x)>(y)?(y):(x))
    #define max(x,y) ((x)>(y)?(x):(y))
    #define RI register ll
    #define db long double
    #define EPS 1e-8
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    inline void put(int x)
    {
        x<0?x=-x,putchar('-'):0;
        int num=0;char ch[20];
        while(x)ch[++num]=x%10+'0',x/=10;
        num==0?putchar('0'):0;
        while(num)putchar(ch[num--]);
        putchar('
    ');return;
    }
    const int MAXN=110,maxn=1100*50;
    int n,m,S,T,ans,t,h,len=1;
    struct wy
    {
        int x,y;
    }s[maxn];
    int vis[maxn],q[maxn];
    int lin[maxn],ver[maxn],nex[maxn];
    db e[maxn];
    inline void add(int x,int y,db z)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;
    }
    inline int bfs()
    {
        memset(vis,0,sizeof(vis));
        t=h=0;q[++t]=S;vis[S]=1;
        while(h++<t)
        {
            int x=q[h];
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(vis[tn])continue;
                if(e[i]<=EPS)continue;
                q[++t]=tn;vis[tn]=vis[x]+1;
                if(tn==T)return 1;
            }
        }
        return 0;
    }
    inline db dfs(int x,db flow)
    {
        if(x==T)return flow;
        db rest=flow,k;
        for(int i=lin[x];i;i=nex[i])
        {
            int tn=ver[i];
            if(rest<=EPS)continue;
            if(vis[tn]==vis[x]+1)
            {
                if(e[i]<=EPS)continue;
                k=dfs(tn,min(e[i],rest));
                if(k<=EPS)vis[tn]=0;
                e[i]-=k;e[i^1]+=k;
                rest-=k;
            }
        }
        return flow-rest;
    }
    inline db dinic()
    {
        db flow=0,maxflow=0;
        while(bfs())while((flow=dfs(S,INF)))maxflow+=flow;
        return maxflow;
    }
    inline db check(db w)
    {
        len=1;
        memset(lin,0,sizeof(lin));
        for(int i=1;i<=m;++i)add(S,i,1),add(i,s[i].x+m,INF),add(i,s[i].y+m,INF);
        for(int i=1;i<=n;++i)add(i+m,T,w);
        return (db)m-dinic();
    }
    inline void dfs(int x)
    {
        vis[x]=1;
        if(x>m&&x<=n+m)++ans;
        for(int i=lin[x];i;i=nex[i])
        {
            int tn=ver[i];
            if(e[i]>EPS&&!vis[tn])dfs(tn);
        }
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();m=read();
        if(!m){puts("1");return 0;}
        S=n+m+1;T=S+1;
        for(int i=1;i<=m;++i)    
        {
            int x,y;
            x=read();y=read();
            s[i]=(wy){x,y};
        }
        db l=0.49,r=(db)m/2.0,eps=(1.0/n)/n;
        while(l+eps<r)
        {
            db mid=(l+r)*0.5;
            if(check(mid)>EPS)l=mid;
            else r=mid;
        }
        check(l);
        memset(vis,0,sizeof(vis));
        dfs(S);
        printf("%d
    ",ans);
        return 0;
    }
    View Code

    费用流:

    bzoj4514 还算比较简单 搞成二分图 注意快速连边的方法即可。

    //#include<bits/stdc++.h>
    #include<iomanip>
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<queue>
    #include<deque>
    #include<cmath>
    #include<ctime>
    #include<cstdlib>
    #include<stack>
    #include<algorithm>
    #include<vector>
    #include<cctype>
    #include<utility>
    #include<set>
    #include<bitset>
    #include<map>
    #define INF 100000000000000000ll
    #define inf 1000000000
    #define ll long long
    #define min(x,y) (x>y?y:x)
    #define max(x,y) (x>y?x:y)
    #define RI register long long
    #define up(p,i,n) for(int i=p;i<=n;++i)
    #define db double
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        int x=0,f=1;char ch=getc();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getc();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
        return x*f;
    }
    //啊 自闭了 写发SDOI找回自信。。
    //SDOI 2016 数字配对。
    //一个数字是ai 有bi个 权值是ci
    //当且仅当ai/aj是质数 两个数字可以配对 显然是最大费用最大流!
    //考虑如何建图 显然的是这是一张二分图建一张即可。注意开ll
    const int MAXN=210*210;
    int n,len=1,h,t,T,S;
    int a[MAXN],b[MAXN],w[MAXN],in[MAXN];
    int q[MAXN],pre[MAXN],vis[MAXN],f[MAXN];
    ll dis[MAXN],sum,e1[MAXN<<1],maxflow,c[MAXN];
    int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],e[MAXN<<1];
    inline void add(int x,int y,int z,ll z1)
    {
        ver[++len]=y;nex[len]=lin[x];lin[x]=len;e[len]=z;e1[len]=z1;
        ver[++len]=x;nex[len]=lin[y];lin[y]=len;e[len]=0;e1[len]=-z1;
    }
    inline void transform(int x)
    {
        int w=a[x],cnt=0;
        for(int i=2;i*i<=a[x];++i)
            while(w%i==0)
            {
                w/=i;
                ++cnt;
            }
        if(w>1)++cnt;
        f[x]=cnt;
    }
    inline int spfa()//最大费用最大流
    {
        for(int i=1;i<=T;++i)dis[i]=-INF;
        t=h=0;dis[S]=0;q[++t]=S;vis[S]=1;in[S]=inf;
        while(h++<t)
        {
            int x=q[h];vis[x]=0;
            for(int i=lin[x];i;i=nex[i])
            {
                int tn=ver[i];
                if(!e[i])continue;
                if(dis[tn]<dis[x]+e1[i])
                {
                    dis[tn]=dis[x]+e1[i];
                    in[tn]=min(in[x],e[i]);
                    pre[tn]=i;
                    if(!vis[tn])q[++t]=tn,vis[tn]=1;
                }
            }
        }
        return dis[T]!=-INF;
    }
    inline void EK()
    {
        while(spfa())
        {
            int x=T,i=pre[x];
            if(sum+in[T]*dis[T]<0)
            {
                maxflow+=sum/(-dis[T]);
                break;
            }
            sum+=in[T]*dis[T];
            maxflow+=in[T];
            while(x!=S)
            {
                e[i]-=in[T];
                e[i^1]+=in[T];
                x=ver[i^1];i=pre[x];
            }
        }
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        n=read();S=n+1;T=S+1;
        for(int i=1;i<=n;++i)a[i]=read(),transform(i);
        for(int i=1;i<=n;++i)b[i]=read();
        for(int i=1;i<=n;++i)c[i]=read();
        for(int i=1;i<=n;++i)
            if(f[i]&1)for(int j=1;j<=n;++j)
                if(((f[i]==f[j]+1)&&(a[i]%a[j]==0))||((f[i]==f[j]-1&&a[j]%a[i]==0)))
                    add(i,j,inf,c[i]*c[j]);
        for(int i=1;i<=n;++i)
            if(f[i]&1)add(S,i,b[i],0);
            else add(i,T,b[i],0);
        EK();
        printf("%lld
    ",maxflow);
        return 0;
    }
    View Code
  • 相关阅读:
    Android开发之LocationManager和定位
    Android开发之SmsManager和SmsMessage
    Android开发之三种动画
    Android开发之ActivityManager获取系统信息
    Android开发之TextView实现跑马灯效果
    Android开发之MD5加密
    linux服务之dns
    java使用Redis(六个类型)
    JedisConnectionException: Failed connecting to host localhost:6379
    下载安装Redis+使用
  • 原文地址:https://www.cnblogs.com/chdy/p/11149079.html
Copyright © 2011-2022 走看看