• bzoj 1001: [BeiJing2006]狼抓兔子


    http://www.lydsy.com/JudgeOnline/problem.php?id=1001

    解法1:直接最小割dinic || isap ,据说会卡掉某些人写的丑的dinic

    /**************************************************************
        Problem: 1497
        User: 11101001
        Language: C++
        Result: Accepted
        Time:576 ms
        Memory:15356 kb
    ****************************************************************/
     
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    using namespace std;
    const int maxn = 600001;
    const int INF = 0x7fffffff;
    int n,m,dis[maxn],head[maxn],que[maxn];
    struct node{
        int v,w,next;
    }edge[maxn];
    int ans,tmp,S,T,num=1;
    inline void Add_Edge(int u,int v,int w)
    {
        edge[++num].v=v;edge[num].w=w;edge[num].next=head[u];head[u]=num;
        edge[++num].v=u;edge[num].next=head[v];head[v]=num;
    }
    bool bfs()
    {
        memset(dis,-1,sizeof(dis));
        int h=0,t=1;
        que[h]=dis[0]=0;
        while(h<t)
        {
            int u=que[h++];
            if(h==maxn)h=0;
            for(int i=head[u];i;i=edge[i].next)
            {
                int v=edge[i].v;
                if(edge[i].w&&dis[v]<0)
                {
                    que[t++]=v;
                    dis[v]=dis[u]+1;
                    if(t==maxn)t=0;
                }
            }
        }
        if(dis[T]==-1)return false;
        return true;
    }
    int dfs(int x,int f)
    {
        if(x==T) return f;
        int mn=0,w;
        for(int i=head[x];i;i=edge[i].next)
        {
            if(edge[i].w&&dis[edge[i].v]==dis[x]+1)
            {
                w=f-mn;
                w=dfs(edge[i].v,min(w,edge[i].w));
                edge[i].w-=w;
                edge[i^1].w+=w;
                mn+=w;
                if(mn==f)return f;
            }   
        }
        if(!mn)dis[x]=-1;
        return mn;
    }
    void dinic()
    {
        while(bfs())
            ans+=dfs(S,INF);
    }
    int main()
    {
        S=0;
        scanf("%d%d",&n,&m);T=n+m+1;
        for(int a,i=1;i<=n;i++){
            scanf("%d",&a);
            Add_Edge(S,i,a);
        }
        for(int a,b,c,i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            Add_Edge(a,n+i,INF);
            Add_Edge(b,n+i,INF);
            Add_Edge(n+i,T,c);
            tmp+=c;
        }
        dinic();
    //  printf("%d %d
    ",tmp,ans);
        printf("%d
    ",tmp-ans);
        return 0;
    }
    Dinic

    解法2:平面图转对偶图最短路.

    /**************************************************************
        Problem: 1001
        User: 11101001
        Language: C++
        Result: Accepted
        Time:2900 ms
        Memory:120432 kb
    ****************************************************************/
     
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define maxn 2000001
    using namespace std;
    int n,m,to;
    struct data{
        int v,next,w;
    }edge[4*maxn];
    int dis[maxn],q[maxn],head[maxn];
    bool vis[maxn];
    int num;
    inline void add_edge(int u,int v,int w)
    {
        edge[++num].v=v;edge[num].w=w;edge[num].next=head[u];head[u]=num;   
        edge[++num].v=u;edge[num].w=w;edge[num].next=head[v];head[v]=num;
    }
    void spfa()
    {
        memset(dis,0x3f,sizeof(dis));
        int t=0,w=1;
        dis[0]=q[w]=0;vis[0]=1;
        while(t!=w)
        {
            int u=q[t++];
            vis[u]=0;
            if(t==maxn)t=0;
            for(int i=head[u];i;i=edge[i].next)
            {
                int v=edge[i].v;
                if(dis[v]>dis[u]+edge[i].w)
                {
                    dis[v]=dis[u]+edge[i].w;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q[w++]=v;
                        if(w==maxn)w=0;
                    }
                }
            }
        }
    }
    inline void init()
    {
            int x;
        for(int j=1;j<m;j++)
        {
            scanf("%d",&x);
            add_edge(j,to+1,x);
        }
        for(int i=1;i<n-1;i++)
        {
            for(int j=1;j<m;j++)
            {
                scanf("%d",&x);
                add_edge((i*2)*(m-1)+j,((i*2)-1)*(m-1)+j,x);
            } 
        }
        for(int j=1;j<m;j++)
        {
            scanf("%d",&x);
            add_edge(0,((n*2)-3)*(m-1)+j,x);
        }
        for(int i=0;i<n-1;i++)
        {
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&x);
                if(j==1)add_edge(0,(i*2)*(m-1)+m,x);
                else if(j==m)add_edge((i*2+1)*(m-1),to+1,x);
                else add_edge((i*2)*(m-1)+j-1,(i*2)*(m-1)+j+m-1,x);
            }
        }
        for(int i=0;i<n-1;i++)
        {
            for(int j=1;j<m;j++)
            {
                scanf("%d",&x);
                add_edge((i*2+1)*(m-1)+j,(i*2)*(m-1)+j,x);
            }
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        to=(n*m-m-n+1)*2;
        init();
        spfa();
        printf("%d
    ",dis[to+1]);
        return 0;
    }
  • 相关阅读:
    Solr的配置和在java中的使用
    druid + mysql + mybatis 批量更新报错
    linux find命令-print0和xargs中-0使用技巧
    Shell 函数相关
    公钥、私钥和数字签名这样最好理解
    Liunx find/locate/whereis/which 总结
    Linux find命令
    Shell bash 数学运算 bc
    Shell 使用 expr 进行数学运算
    Shell 有类型变量
  • 原文地址:https://www.cnblogs.com/sssy/p/8097319.html
Copyright © 2020-2023  润新知