• MUTC 1 E Seikimatsu Occult Tonneru 枚举 网络流


    Seikimatsu Occult Tonneru

    Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 1341    Accepted Submission(s): 313


    Problem Description
    During the world war, to avoid the upcoming Carpet-bombing from The Third Reich, people in Heaven Empire went to Great Tunnels for sheltering.
    There are N cities in Heaven Empire, where people live, with 3 kinds of directed edges connected with each other. The 1st kind of edges is one of Great Tunnels( no more than 20 tunnels) where a certain number of people can hide here; people can also go through one tunnel from one city to another. The 2nd kind of edges is the so-called Modern Road, which can only let people go through. The 3rd kind of edges is called Ancient Bridge and all the edges of this kind have different names from others, each of which is named with one of the twelve constellations( such as Libra, Leo and so on); as they were build so long time ago, they can be easily damaged by one person's pass. Well, for each bridge, you can spend a certain deal of money to fix it. Once repaired, the 3rd kind of edges can let people pass without any limitation, namely, you can use one bridge to transport countless people. As for the former two kinds of edges, people can initially go through them without any limitation.
    We want to shelter the most people with the least money.
    Now please tell me the largest number of people who can hide in the Tunnels and the least money we need to spend to realize our objective.
     

    Input
    Multiple Cases.
    The first line, two integers: N (N<=100), m (m<=1000). They stands for the number of cities and edges.
    The next line, N integers, which represent the number of people in the N cities.
    Then m lines, four intergers each: u, v, w, p (1<=u, v<=N, 0<=w<=50). A directed edge u to v, with p indicating the type of the edge: if it is a Tunnel then p < 0 and w means the maximum number people who can hide in the the tunnel; if p == 0 then it is a Modern Road with w means nothing; otherwise it is an Ancient Bridge with w representing the cost of fixing the bridge. We promise there are no more than one edge from u to v.
     

    Output
    If nobody can hide in the Tunnels, print “Poor Heaven Empire”, else print two integers: maximum number and minimum cost.
     

    Sample Input
    4 4 2 1 1 0 1 2 0 0 1 3 0 0 2 4 1 -1 3 4 3 -1 4 4 2 1 1 0 1 2 0 0 1 3 3 1 2 4 1 -1 3 4 3 -1
     

    Sample Output
    4 0 4 3
     

    Author
    BUPT
     

    Source
     

    Recommend
    zhuyuanchen520
     

    -----------------

    最大流

    建图:

    从S向城市i连接一条容量为人数的边。

    对每条边

    ①p<0时,从u向T连接一条容量为人数的边,从u向v连接一条容量为OO的边

    ②p=0时,从u向T连接一条容量为无穷大的边

    ③p>0时,枚举是否修复。修复的情况从u向v连接一条容量为OO的边,累积花费;不修复的情况从u向v连接一条容量为1的边,无花费。

    枚举每条待修复的边,最多有2^12种方案。

    -----------------

    用黄大神的Dinic模板AC,用白书的模板超时

    -----------------

    更快的

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    
    using namespace std;
    
    const int OO=1e9;
    const int maxm=111111;
    const int maxn=999;
    
    struct edgenode
    {
        int to,flow,next;
    };
    
    struct Dinic
    {
        int node,src,dest,edge;
        int head[maxn],work[maxn],dis[maxn],q[maxn];
        edgenode edges[maxm];
    
        void prepare(int _node,int _src,int _dest)
        {
            node=_node,src=_src,dest=_dest;
            for (int i=0; i<node; i++) head[i]=-1;
            edge=0;
        }
    
        void addedge(int u,int v,int c)
        {
            edges[edge].flow=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
            edges[edge].flow=0,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++;
        }
    
        bool Dinic_bfs()
        {
            int i,u,v,l,r=0;
            for (i=0; i<node; i++) dis[i]=-1;
            dis[q[r++]=src]=0;
            for (l=0; l<r; l++){
                for (i=head[u=q[l]]; i!=-1; i=edges[i].next){
                    if (edges[i].flow&&dis[v=edges[i].to]<0){
                        dis[q[r++]=v]=dis[u]+1;
                        if (v==dest) return true;
                    }
                }
            }
            return false;
        }
    
        int Dinic_dfs(int u,int exp)
        {
            if (u==dest) return exp;
            for (int &i=work[u],v,tmp; i!=-1; i=edges[i].next){
                if (edges[i].flow&&dis[v=edges[i].to]==dis[u]+1&&
                    (tmp=Dinic_dfs(v,min(exp,edges[i].flow)))>0){
                    edges[i].flow-=tmp;
                    edges[i^1].flow+=tmp;
                    return tmp;
                }
            }
            return 0;
        }
    
        int Dinic_flow()
        {
            int i,ret=0,delta;
            while (Dinic_bfs()){
                for (i=0; i<node; i++) work[i]=head[i];
                while ( delta=Dinic_dfs(src,OO) ) ret+=delta;
            }
            return ret;
        }
    
    }solver;
    
    int ogc[14];
    int cst[14];
    int cnt;
    int ww[maxn];
    int main()
    {
        int n,m;
        int mincost,maxnum,cost,num;
        while (~scanf("%d%d",&n,&m))
        {
            cnt=0;
            solver.prepare(n+2,0,n+1);
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&ww[i]);
                solver.addedge(solver.src,i,ww[i]);
            }
            for (int i=0;i<m;i++)
            {
                int u,v,w,p;
                scanf("%d%d%d%d",&u,&v,&w,&p);
                if (p<0)
                {
                    solver.addedge(u,solver.dest,w);
                    solver.addedge(u,v,OO);
                }
                if (p>0)
                {
                    solver.addedge(u,v,1);
                    cst[cnt]=w;
                    ogc[cnt++]=solver.edge-2;
    
                }
                if (p==0)
                {
                    solver.addedge(u,v,OO);
                }
            }
            mincost=0;
            maxnum=0;
            for (int i=0;i<(1<<cnt);i++)
            {
                cost=0;
                num=0;
                for (int k=0;k<solver.edge;k+=2)
                {
                    solver.edges[k].flow+=solver.edges[k^1].flow;
                    solver.edges[k^1].flow=0;
                }
                for (int j=0;j<cnt;j++)
                {
                    if (i&(1<<j))
                    {
                        solver.edges[ogc[j]].flow=OO;
                        cost+=cst[j];
                    }
                    else
                    {
                        solver.edges[ogc[j]].flow=1;
                    }
                }
                num=solver.Dinic_flow();
                if (num>maxnum)
                {
                    maxnum=num;
                    mincost=cost;
                }
                else if (num==maxnum&&cost<mincost)
                {
                    mincost=cost;
                }
            }
            if (maxnum>0)
            {
                printf("%d %d\n",maxnum,mincost);
            }
            else
            {
                puts("Poor Heaven Empire");
            }
    
        }
        return 0;
    }



    ---------------

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    
    using namespace std;
    
    const int OO=1e9;
    const int maxm=111111;
    const int maxn=999;
    
    struct edgenode
    {
        int to,flow,next;
    };
    
    struct Dinic
    {
        int node,src,dest,edge;
        int head[maxn],work[maxn],dis[maxn],q[maxn];
        edgenode edges[maxm];
    
        void prepare(int _node,int _src,int _dest)
        {
            node=_node,src=_src,dest=_dest;
            for (int i=0; i<node; i++) head[i]=-1;
            edge=0;
        }
    
        void addedge(int u,int v,int c)
        {
            edges[edge].flow=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
            edges[edge].flow=0,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++;
        }
    
        bool Dinic_bfs()
        {
            int i,u,v,l,r=0;
            for (i=0; i<node; i++) dis[i]=-1;
            dis[q[r++]=src]=0;
            for (l=0; l<r; l++){
                for (i=head[u=q[l]]; i!=-1; i=edges[i].next){
                    if (edges[i].flow&&dis[v=edges[i].to]<0){
                        dis[q[r++]=v]=dis[u]+1;
                        if (v==dest) return true;
                    }
                }
            }
            return false;
        }
    
        int Dinic_dfs(int u,int exp)
        {
            if (u==dest) return exp;
            for (int &i=work[u],v,tmp; i!=-1; i=edges[i].next){
                if (edges[i].flow&&dis[v=edges[i].to]==dis[u]+1&&
                    (tmp=Dinic_dfs(v,min(exp,edges[i].flow)))>0){
                    edges[i].flow-=tmp;
                    edges[i^1].flow+=tmp;
                    return tmp;
                }
            }
            return 0;
        }
    
        int Dinic_flow()
        {
            int i,ret=0,delta;
            while (Dinic_bfs()){
                for (i=0; i<node; i++) work[i]=head[i];
                while ( delta=Dinic_dfs(src,OO) ) ret+=delta;
            }
            return ret;
        }
    
    }solver;
    
    int thead[maxn];
    edgenode tedges[maxm];
    int tedge_num;
    
    struct OGC{
        int u,v,w;
    }ogc[14];
    int cnt;
    int ww[maxn];
    int main()
    {
        int n,m;
        int mincost,maxnum,cost,num;
        while (~scanf("%d%d",&n,&m))
        {
            cnt=0;
            solver.prepare(n+2,0,n+1);
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&ww[i]);
                solver.addedge(solver.src,i,ww[i]);
            }
            for (int i=0;i<m;i++)
            {
                int u,v,w,p;
                scanf("%d%d%d%d",&u,&v,&w,&p);
                if (p<0)
                {
                    solver.addedge(u,solver.dest,w);
                    solver.addedge(u,v,OO);
                }
                if (p>0)
                {
                    //solver.addedge(u,v,1);
                    ogc[cnt].u=u;
                    ogc[cnt].v=v;
                    ogc[cnt].w=w;
                    cnt++;
                }
                if (p==0)
                {
                    solver.addedge(u,v,OO);
                }
            }
            memcpy(thead,solver.head,sizeof(thead));
            memcpy(tedges,solver.edges,sizeof(tedges));
            tedge_num=solver.edge;
            mincost=0;
            maxnum=0;
            for (int i=0;i<(1<<cnt);i++)
            {
                solver.edge=tedge_num;
                memcpy(solver.head,thead,sizeof(solver.head));
                memcpy(solver.edges,tedges,sizeof(solver.edges));
                cost=0;
                num=0;
                for (int j=0;j<cnt;j++)
                {
                    if (i&(1<<j))
                    {
                        solver.addedge(ogc[j].u,ogc[j].v,OO);
                        cost+=ogc[j].w;
                    }
                    else
                    {
                        solver.addedge(ogc[j].u,ogc[j].v,1);
                    }
                }
                num=solver.Dinic_flow();
                if (num>maxnum)
                {
                    maxnum=num;
                    mincost=cost;
                }
                else if (num==maxnum&&cost<mincost)
                {
                    mincost=cost;
                }
            }
            if (maxnum>0)
            {
                printf("%d %d\n",maxnum,mincost);
            }
            else
            {
                puts("Poor Heaven Empire");
            }
    
        }
        return 0;
    }
    
    /*
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <set>
    
    using namespace std;
    
    const int maxn=1111;
    const int maxm=1111111;
    const int INF=1e9;
    
    struct Edge{
        int from,to,cap,flow;
    };
    
    struct Dinic{
        int n,m,s,t;
        vector<Edge>edges;
        vector<int>G[maxn];
        bool vis[maxn];
        int d[maxn];
        int cur[maxn];
    
        void init(int n){
            this->n=n;
            for (int i=0;i<n;i++) G[i].clear();
            edges.clear();
            m=0;
        }
    
        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(){
            memset(vis,0,sizeof(vis));
            queue<int>que;
            que.push(s);
            d[s]=0;
            vis[s]=true;
            while (!que.empty()){
                int x=que.front();que.pop();
                for (int i=0;i<G[x].size();i++){
                    Edge& e=edges[G[x][i]];
                    if (!vis[e.to]&&e.cap>e.flow){
                        vis[e.to]=true;
                        d[e.to]=d[x]+1;
                        que.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[x]+1==d[e.to]&&(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 Maxflow(int s,int t){
            this->s=s;
            this->t=t;
            int flow=0;
            while (BFS()){
                memset(cur,0,sizeof(cur));
                flow+=DFS(s,INF);
            }
            return flow;
        }
    
    }solver;
    
    vector<Edge>tmpedges;
    
    struct OGC{
        int u,v,w;
    }ogc[14];
    int cnt;
    int ww[maxn];
    int main()
    {
        int n,m;
        int mincost,maxnum,cost,num;
        int s,t;
        while (~scanf("%d%d",&n,&m))
        {
            cnt=0;
            solver.init(n+2);
            s=0;
            t=n+1;
            for (int i=1;i<=n;i++)
            {
                scanf("%d",&ww[i]);
                solver.addedge(s,i,ww[i]);
            }
            for (int i=0;i<m;i++)
            {
                int u,v,w,p;
                scanf("%d%d%d%d",&u,&v,&w,&p);
                if (p<0)
                {
                    solver.addedge(u,t,w);
                    solver.addedge(u,v,INF);
                }
                if (p>0)
                {
                    //solver.addedge(u,v,1);
                    ogc[cnt].u=u;
                    ogc[cnt].v=v;
                    ogc[cnt].w=w;
                    cnt++;
                }
                if (p==0)
                {
                    solver.addedge(u,v,INF);
                }
            }
            tmpedges=solver.edges;
            mincost=0;
            maxnum=0;
            for (int i=0;i<(1<<cnt);i++)
            {
                solver.edges=tmpedges;
                cost=0;
                num=0;
                for (int j=0;j<cnt;j++)
                {
                    if (i&(1<<j))
                    {
                        solver.addedge(ogc[j].u,ogc[j].v,INF);
                        cost+=ogc[j].w;
                    }
                    else
                    {
                        solver.addedge(ogc[j].u,ogc[j].v,1);
                    }
                }
                num=solver.Maxflow(s,t);
                if (num>maxnum)
                {
                    maxnum=num;
                    mincost=cost;
                }
                else if (num==maxnum&&cost<mincost)
                {
                    mincost=cost;
                }
            }
            if (maxnum>0)
            {
                printf("%d %d\n",maxnum,mincost);
            }
            else
            {
                puts("Poor Heaven Empire");
            }
    
        }
        return 0;
    }
    */
    





  • 相关阅读:
    【转】 Shiro 核心功能案例讲解 基于SpringBoot 有源码
    【转】 SpringData 基于SpringBoot快速入门
    【转】 Dubbo整合SpringBoot
    【转】 SpringBoot war包部署到Tomcat服务器
    【转】 SpringBoot使用Redis缓存
    【转】 SpringBoot统一异常处理
    【转】 SpringBoot创建定时任务
    【转】 SpringBoot 多环境配置
    js小数运算出现误差
    vue中组件的data为什么是一个函数
  • 原文地址:https://www.cnblogs.com/cyendra/p/3226309.html
Copyright © 2020-2023  润新知