• 最大流拆点——hdu2732,poj3436


    一种很普遍的做法就是把一个带有容量的点拆成两个点,一个入点一个出点,链接两个点的边的权值为这个点的容量

    hdu3732

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<string>
    #include<iostream>
    #define INF 1e9
    using namespace std;
    const int maxn =1000+10;
     
    struct Edge
    {
        int from,to,cap,flow;
        Edge(){}
        Edge(int f,int t,int c,int fl):from(f),to(t),cap(c),flow(fl){}
    };
     
    struct Dinic
    {
        int n,m,s,t;
        vector<Edge> edges;
        vector<int> G[maxn];
        int cur[maxn];
        int d[maxn];
        bool vis[maxn];
     
        void init(int n,int s,int t)
        {
            this->n=n, this->s=s, this->t=t;
            edges.clear();
            for(int i=0;i<n;i++) G[i].clear();
        }
     
        void AddEdge(int from,int to,int cap)
        {
            edges.push_back( Edge(from,to,cap,0) );
            edges.push_back( Edge(to,from,0,0) );
            m = edges.size();
            G[from].push_back(m-2);
            G[to].push_back(m-1);
        }
     
        bool BFS()
        {
            queue<int> Q;
            Q.push(s);
            memset(vis,0,sizeof(vis));
            d[s]=0;
            vis[s]=true;
            while(!Q.empty())
            {
                int x=Q.front(); Q.pop();
                for(int i=0;i<G[x].size();++i)
                {
                    Edge& e=edges[G[x][i]];
                    if(!vis[e.to] && e.cap>e.flow)
                    {
                        d[e.to]=1+d[x];
                        vis[e.to]=true;
                        Q.push(e.to);
                    }
                }
            }
            return vis[t];
        }
     
        int DFS(int x,int a)
        {
            if(x==t || a==0) return a;
            int flow=0,f;
            for(int& i=cur[x];i<G[x].size();++i)
            {
                Edge& e=edges[G[x][i]];
                if(d[e.to]==d[x]+1 && (f=DFS(e.to,min(a,e.cap-e.flow) ) )>0)
                {
                    e.flow +=f;
                    edges[G[x][i]^1].flow -=f;
                    flow +=f;
                    a-=f;
                    if(a==0) break;
                }
            }
            return flow;
        }
     
        int max_flow()
        {
            int ans=0;
            while(BFS())
            {
                memset(cur,0,sizeof(cur));
                ans += DFS(s,INF);
            }
            return ans;
        }
    }DC;
     
    int main()
    {
        int T; scanf("%d",&T);
        for(int kase=1;kase<=T;++kase)
        {
            int n,m,d,src,dst;
            int sum=0;//蜥蜴数
            scanf("%d%d",&n,&d);
            for(int i=1;i<=n;i++)
            {
                string s;
                cin>>s;
                if(i==1)//第一次
                {
                    m = s.size();
                    src=0, dst=2*n*m+1;
                    DC.init(2*n*m+2,src,dst);
                }
                for(int j=0;j<s.size();++j)if(s[j]-'0'>0)
                {
                    int id = (i-1)*m+j+1;//当前点编号
                    DC.AddEdge(id, id+n*m, s[j]-'0');
                    if(i<=d || i+d>n || j<d || j+d>=m)//当前格子能直接跳出棋盘
                    {
                        DC.AddEdge(id+n*m,dst,INF);
                    }
                    else //不能直接跳出去
                    {
                        for(int k=1;k<=n;k++)
                        for(int h=0;h<m;h++)
                        {
                            int id2= (k-1)*m+h+1;
                            if(id==id2) continue;
                            if(abs(i-k)+abs(j-h)<= d) DC.AddEdge(id+n*m,id2,INF);
                        }
                    }
                }
            }
            for(int i=1;i<=n;++i)
            {
                string s;
                cin>>s;
                for(int j=0;j<s.size();++j)
                {
                    int id = (i-1)*m+j+1;//当前点编号
                    if(s[j]=='L')
                    {
                        ++sum;
                        DC.AddEdge(src,id,1);
                    }
                }
            }
            int ans = sum-DC.max_flow();
            if(ans==0) printf("Case #%d: no lizard was left behind.
    ",kase);
            else if(ans==1) printf("Case #%d: 1 lizard was left behind.
    ",kase);
            else printf("Case #%d: %d lizards were left behind.
    ",kase,ans);
        }
        return 0;
    }
    View Code

    poj3436

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define Maxn 110
    using namespace std;
     
    const int inf=0x3f3f3f3f;
    struct line{
        int to,next,cap;
    }p[Maxn*Maxn*2];
    int head[Maxn];
    int q[Maxn];
    int d[Maxn]; 
    int cur[Maxn]; 
    int tot; 
    int src,t;
    int n,m;
    void addedge(int a,int b,int c){
        p[tot].to=b;
        p[tot].next=head[a];
        p[tot].cap=c;
        head[a]=tot++;
    }
    void insert(int a,int b,int c){
        addedge(a,b,c);
        addedge(b,a,0);
    }
    bool bfs(){
        memset(d,-1,sizeof d);
        int s=0,e=-1;
        q[++e]=src;
        d[src]=0;
        while(s<=e){
            int u=q[s++];
            for(int i=head[u];i!=-1;i=p[i].next){
                int v=p[i].to;
                if(d[v]==-1&&p[i].cap){
                    d[v]=d[u]+1;
                    q[++e]=v;
                }
            }
        }
        return d[t]!=-1;
    }
    int dfs(int u,int alpha){ 
        if(u==t) return alpha;
        int w,used=0;
        for(int i=cur[u];i!=-1&&used<alpha;i=p[i].next){ 
            int v=p[i].to;
            if(p[i].cap&&d[v]==d[u]+1){
                w=dfs(v,min(alpha-used,p[i].cap));
                used+=w;
                p[i].cap-=w;
                p[i^1].cap+=w;
                cur[u]=i;
            }
        }
        if(!used) d[u]=-1;
        return used;
    }
    int dinic(){ 
        int ans=0;
        src=0,t=2*m+1; 
        while(bfs()){
            for(int i=src;i<=t;i++) cur[i]=head[i]; 
            ans+=dfs(src,inf);
        }
        return ans;
    }
    int num[Maxn];
    int input[Maxn][20],output[Maxn][20];
    int vis[Maxn][Maxn];
    bool check(int x,int y){
        return x==y||y==2;
    }
    bool ck1(int d){ //没有1
        for(int i=0;i<n;i++)
            if(input[d][i]==1) return false;
        return true;
    }
    bool ck2(int d){ //全1
        for(int i=0;i<n;i++)
            if(output[d][i]!=1) return false;
        return true;
    }
    int main()
    {
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=m;i++){
                scanf("%d",num+i);
                for(int j=0;j<n;j++)
                    scanf("%d",&input[i][j]);
                for(int j=0;j<n;j++)
                    scanf("%d",&output[i][j]);
            }
            memset(head,-1,sizeof head);
            memset(vis,0,sizeof vis);
            tot=0;
            for(int i=1;i<=m;i++)
                for(int j=1;j<=m;j++){
                    if(i==j) continue;
                    bool flag=true;
                    for(int k=0;k<n;k++)
                        if(!check(output[i][k],input[j][k])){
                            flag=false;
                            break;
                        }
                    if(flag){
                        insert(i+m,j,num[i]);
                        vis[i+m][j]=1;
                    }
                }
            for(int i=1;i<=m;i++){
                insert(i,i+m,num[i]); //拆点
                if(ck1(i)) insert(0,i,num[i]);
                if(ck2(i)) insert(i+m,2*m+1,num[i]);
            }
            printf("%d",dinic());
            int cnt=0;
            for(int i=1;i<=m;i++){
                for(int j=head[i+m];j!=-1;j=p[j].next)
                    if(vis[i+m][p[j].to]&&p[j].cap<num[i]) cnt++;
            }
            printf(" %d
    ",cnt);
            for(int i=1;i<=m;i++){
                for(int j=head[i+m];j!=-1;j=p[j].next)
                    if(vis[i+m][p[j].to]&&p[j].cap<num[i]){
                        printf("%d %d %d
    ",i,p[j].to,num[i]-p[j].cap);
                    }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    51nod 2080 最长上升子序列
    common js
    es Module
    git关于分支的常用操作
    react实现浏览器的返回、前进、刷新,关闭拦截
    Blob,ArrayBuffer,FileReader,FormData,Buffer的理解
    memo、useCallback、useMemo三者的区别
    npm 和 yarn的全局安装位置
    react中单行文本溢出省略号
    react中基于styled-components组件的一像素边框问题
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10991890.html
Copyright © 2020-2023  润新知