最大流拆点——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.\n",kase);
        else if(ans==1) printf("Case #%d: 1 lizard was left behind.\n",kase);
        else printf("Case #%d: %d lizards were left behind.\n",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\n",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\n",i,p[j].to,num[i]-p[j].cap);
                }
        }
    }
    return 0;
}
View Code

 

posted on 2019-06-08 22:00  zsben  阅读(83)  评论(0编辑  收藏  举报

导航