hdu 4309 Seikimatsu Occult Tonneru 网络流

来源:互联网 发布:sql语句中的关键字 编辑:程序博客网 时间:2024/06/04 18:58

题意:

有三种不同类型的边,一种可以在里面放人,一种可以任意多人穿过,一种可以过一个人,如果通过了一个人之后可以选择增加花费使得可以通过无限的人数。有N个城市,要把尽可能多的人放在第一种里面,问最少需要多少花费。


思路:

可以转化为网络流模型,第一种边拆开就好,如(x,y)连成,x->u,u->T,x-y,这样就好,其他的就枚举第三种选择那些就好,(因为第三种只有12条)。


代码如下:


#include<cstdio>#include<cstring>#include<algorithm>#include<cmath>#include<queue>#include<set>#include<vector>using namespace std;typedef __int64 ll;const int maxnode=4000+5;const int maxedge=1000000+5;const int oo=1000000000;struct Dinic{    int node,src,dest,nedge;    int head[maxnode],point[maxedge],next[maxedge],flow[maxedge],capa[maxedge];    int dist[maxnode],Q[maxnode],work[maxnode];    void init(int _node,int _src,int _dest)    {        node=_node;        src=_src;        dest=_dest;        for(int i=0; i<node; i++) head[i]=-1;        nedge=0;    }    void addedge(int u,int v,int c1,int c2)    {        point[nedge]=v,capa[nedge]=c1,flow[nedge]=0,next[nedge]=head[u],head[u]=(nedge++);        point[nedge]=u,capa[nedge]=c2,flow[nedge]=0,next[nedge]=head[v],head[v]=(nedge++);    }    bool dinic_bfs()    {        memset(dist,255,sizeof(dist));        dist[src]=0;        int sizeQ=0;        Q[sizeQ++]=src;        for(int cl=0; cl<sizeQ; cl++)        {            for(int k=Q[cl],i=head[k]; i>=0; i=next[i])            {                if(flow[i]<capa[i] && dist[point[i]]<0)                {                    dist[point[i]]=dist[k]+1;                    Q[sizeQ++]=point[i];                }            }        }        return dist[dest]>=0;    }    int dinic_dfs(int x,int exp)    {        if(x==dest) return exp;        for(int &i=work[x]; i>=0; i=next[i])        {            int v=point[i],tmp;            if(flow[i]<capa[i] && dist[v]==dist[x]+1 && (tmp = dinic_dfs(v,min(exp,capa[i]-flow[i])))>0)            {                flow[i]+=tmp;                flow[i^1]-=tmp;                return tmp;            }        }        return 0;    }    int dinic_flow()    {        int result=0;        while(dinic_bfs())        {            for(int i=0; i<node; i++) work[i]=head[i];            while(1)            {                int delta=dinic_dfs(src,oo);                if(delta==0) break;                result +=delta;            }        }        return result;    }} Solver;int N,m;int num_tunnel,num_modern,num_ancient;int num[110];int tun[33],modern[1010],anc[33];int ut[33],vt[33],um[1010],vm[1010],ua[33],va[33];int res,sum_cost;bool choose[33];void cal(){    int tcost=0;    for(int i=1; i<=num_ancient; i++)    {        if(choose[i])tcost+=anc[i];    }//printf("tcost=%d\n",tcost);    if(tcost>=sum_cost)return;    Solver.init(num_tunnel+N+2,0,num_tunnel+N+1);    for(int i=1; i<=N; i++)    {        Solver.addedge(0,i,num[i],0);    }    for(int i=1; i<=num_tunnel; i++)    {        Solver.addedge(N+i,num_tunnel+N+1,tun[i],0);        Solver.addedge(ut[i],N+i,oo,0);        //Solver.addedge(vt[i],N+i,oo,0);        Solver.addedge(ut[i],vt[i],oo,0);    }    for(int i=1; i<=num_modern; i++)    {        Solver.addedge(um[i],vm[i],oo,0);    }    for(int i=1; i<=num_ancient; i++)    {        if(choose[i])        {            Solver.addedge(ua[i],va[i],oo,0);        }        else        {            Solver.addedge(ua[i],va[i],1,0);        }    }    int t=Solver.dinic_flow();    if(t>=res)    {        sum_cost=tcost;    }}void first(){    Solver.init(num_tunnel+N+2,0,num_tunnel+N+1);    for(int i=1; i<=N; i++)    {        Solver.addedge(0,i,num[i],0);    }    for(int i=1; i<=num_tunnel; i++)    {        Solver.addedge(N+i,num_tunnel+N+1,tun[i],0);        Solver.addedge(ut[i],N+i,oo,0);       // Solver.addedge(vt[i],N+i,oo,0);        Solver.addedge(ut[i],vt[i],oo,0);    }    for(int i=1; i<=num_modern; i++)    {        Solver.addedge(um[i],vm[i],oo,0);    }    for(int i=1; i<=num_ancient; i++)    {        Solver.addedge(ua[i],va[i],oo,0);    }    res=Solver.dinic_flow();}void dfs(int ind){    if(ind>num_ancient)    {        //for(int i=1;i<=num_ancient;i++)printf("%d ",choose[i]);printf("\n");        cal();    }    else    {        choose[ind]=false;        dfs(ind+1);        choose[ind]=true;        dfs(ind+1);        choose[ind]=false;    }}int main(){    while(scanf("%d",&N)!=EOF)    {        scanf("%d",&m);        num_tunnel=0;        num_ancient=0;        num_modern=0;        sum_cost=0;        for(int i=1; i<=N; i++)        {            scanf("%d",&num[i]);        }        for(int i=1; i<=m; i++)        {            int u,v,w,p;            scanf("%d%d%d%d",&u,&v,&w,&p);            if(p<0)            {                tun[++num_tunnel]=w;                ut[num_tunnel]=u;                vt[num_tunnel]=v;            }            else if(p==0)            {                modern[++num_modern]=w;                um[num_modern]=u;                vm[num_modern]=v;            }            else            {                sum_cost+=w;                anc[++num_ancient]=w;                ua[num_ancient]=u;                va[num_ancient]=v;            }        }        //printf("@@%d\n",sum_cost);        first();        if(res<=0)        {            printf("Poor Heaven Empire\n");        }        else        {            memset(choose,false,sizeof(choose));            dfs(1);            printf("%d %d\n",res,sum_cost);        }    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 十个月小孩不爱吃饭怎么办 十个月的小孩不吃饭怎么办 家长要调幼儿园监控怎么办 自己带孩子婆婆生气怎么办 婆婆老是觉得我奶水不够怎么办 1岁小儿特别懒怎么办 17的孩子很懒怎么办 上大班的孩子不愿写字怎么办 快上中班的小朋友不爱学习怎么办 小学生两边肩膀不平应该怎么办 写字右肩膀疼是怎么办 开车久了肩膀疼怎么办 3岁宝宝撕书怎么办 孩子上幼儿园不爱写字怎么办 一年级小孩不爱做作业怎么办 小孩不愿多做作业怎么办 小孩一年级不自觉做作业怎么办 小孩会读不会写怎么办 好多字都不会写怎么办 写作业怎么办才能写快 五周宝宝爱玩不写字怎么办 爱玩手机的小孩怎么办? 一年级学生记不住生字怎么办 一年级小孩记不住生字怎么办 配镜度数高了怎么办 宝宝两岁半不肯坐马桶拉臭臭怎么办 儿子字写得不好 怎么办 小孩不听话不爱读书和写字怎么办 两岁宝宝不愿意穿衣服怎么办 做题粗心不认真怎么办 5岁宝宝不会写字怎么办 四岁宝宝不会写字怎么办 4岁宝宝不写字怎么办 四岁宝宝不写字怎么办 孩子学习粗心计算能力差怎么办 一年级的小朋友不爱看书怎么办 马上要生了害怕怎么办 孩子做题不爱读题怎么办 孩子作业写的慢怎么办 孩子学习不好怎么办我们有绝招 英语不会做题怎么办呢?