hdu 4309 状压+最大流

来源:互联网 发布:dpp软件 编辑:程序博客网 时间:2024/06/05 22:34

传送门

题目大意:有n个城市,每个城市有一个人数,城市与城市之间有三种通道(均为单向):隧道,公路和桥。隧道和公路都可以通过无限制的人,并且隧道可以避难ai人。桥没有修理的时候只能通过一个人次,修理之后就和公路没有差别了,修理有费用。特别注意桥不超过12条。求通过最大人数,最少修理话费。

最多只有12个。。。。直接枚举可能就过了--4000+种可能情况而已。每次输入的时候记录有多少个桥需要修 cnt++ 状压枚举的时候一定是枚举修桥之后的情况

枚举方法(状压 1<<cnt


每个状态求一次流量,然后更新答案。



#include <iostream>#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;const int maxn = 60007;const int maxm = 65000;const int oo = 99999999;int idx;int cur[maxn], pre[maxn];int dis[maxn], gap[maxn];int aug[maxn], head[maxn];struct Node{    int u, v, w;    int next;}edge[maxm];void addEdge(int u, int v, int w){    edge[idx].u = u;    edge[idx].v = v;    edge[idx].w = w;    edge[idx].next = head[u];    head[u] = idx++;    edge[idx].u = v;    edge[idx].v = u;    edge[idx].w = 0;    edge[idx].next = head[v];    head[v] = idx++;}int SAP(int s, int e, int n){    int max_flow = 0, v, u = s;    int id, mindis;    aug[s] = oo;    pre[s] = -1;    memset(dis, 0, sizeof(dis));    memset(gap, 0, sizeof(gap));    gap[0] = n; // 我觉得这一句要不要都行,因为dis[e]始终为0    for (int i = 0; i <= n; ++i)    {   // 初始化当前弧为第一条弧        cur[i] = head[i];    }    while (dis[s] < n)    {        bool flag = false;        if (u == e)        {            max_flow += aug[e];            for (v = pre[e]; v != -1; v = pre[v]) // 路径回溯更新残留网络            {                id = cur[v];                edge[id].w -= aug[e];                edge[id^1].w += aug[e];                aug[v] -= aug[e]; // 修改可增广量,以后会用到                if (edge[id].w == 0) u = v; // 不回退到源点,仅回退到容量为0的弧的弧尾            }        }        for (id = cur[u]; id != -1; id = edge[id].next)        {   // 从当前弧开始查找允许弧            v = edge[id].v;            if (edge[id].w > 0 && dis[u] == dis[v] + 1) // 找到允许弧            {                flag = true;                pre[v] = u;                cur[u] = id;                aug[v] = min(aug[u], edge[id].w);                u = v;                break;            }        }        if (flag == false)        {            if (--gap[dis[u]] == 0) break; /* gap优化,层次树出现断层则结束算法 */            mindis = n;            cur[u] = head[u];            for (id = head[u]; id != -1; id = edge[id].next)            {                v = edge[id].v;                if (edge[id].w > 0 && dis[v] < mindis)                {                    mindis = dis[v];                    cur[u] = id; // 修改标号的同时修改当前弧                }            }            dis[u] = mindis + 1;            gap[dis[u]]++;            if (u != s) u = pre[u]; // 回溯继续寻找允许弧        }    }    return max_flow;}int val[1010];struct node{    int u,v,w,p;}Q[1010];//int map[300][300];int main(){    int t, n, m, pi, si, ei;    int Max, sum, source, sink, vn;    //scanf("%d", &t);    t=1;    for (int cas = 1; cas <= t; ++cas)    {        //scanf("%d%d",&n,&m);        while(scanf("%d%d",&n,&m)!=EOF)        {            int flag=0;            for(int i=1;i<=n;i++)                scanf("%d",&val[i]);          //  getchar();            int cnt=0;            for(int i=1;i<=m;i++)            {                scanf("%d%d%d%d",&Q[i].u,&Q[i].v,&Q[i].w,&Q[i].p);                if(Q[i].p>0)                    cnt++;                if(Q[i].p<0&&Q[i].w!=0)                {                    flag=1;                   // cout<<"*****"<<endl;                }               // cout<<Q[i].p<<" ";            }            if(!flag)            {                puts("Poor Heaven Empire");                continue;            }            int mm=(1<<cnt);            int maxnum=-oo,mincost=0;            for(int k=0;k<mm;k++)            {                idx = 0;                source = 0;sink = n + 1; vn = sink + 1;                memset(head, -1, sizeof(head));                sum = 0;  Max = 0;           /* for (int i = 1; i <= n; ++i)            {                scanf("%d %d %d", &pi, &si, &ei);                sum += pi;                Max = max(Max, ei);                addEdge(source, i, pi);                for (int j = si; j <= ei; ++j)                {                    addEdge(i, n + j, 1);                }            }  */                //cout<<endl;                int j=0,cost=0;                for(int i=1;i<=n;i++)                    addEdge(0,i,val[i]);                for(int i=1;i<=m;i++)                {                    //cout<<Q[i].u<<" "<<Q[i].v<<" "<<Q[i].w<<" "<<Q[i].p<<endl;                    if(Q[i].p<0)                    {                        addEdge(Q[i].u,Q[i].v,oo);                        addEdge(Q[i].u,sink,Q[i].w);                    }                    else if(Q[i].p==0)                        addEdge(Q[i].u,Q[i].v,oo);                    else                    {                        //cout<<Q[i].p<<"   ****"<<endl;                        if(k&(1<<j))                        {                            addEdge(Q[i].u,Q[i].v,oo);                            cost+=Q[i].w;                           // cout<<cost<<endl;                        }                        else addEdge(Q[i].u,Q[i].v,1);                        j++;                    }                }                int ans=SAP(0,sink,vn);                if(ans>maxnum||(ans==maxnum&&cost<mincost))                {                    maxnum=ans;                    mincost=cost;                }            }            if(maxnum>0)                printf("%d %d\n",maxnum,mincost);            else printf("Poor Heaven Empire\n");            /*for (int i = 1; i <= Max; ++i)            {                addEdge(n + i, sink, m);            }            if (SAP(source, sink, vn) == sum)                printf("Case %d: Yes\n\n", cas);            else printf("Case %d: No\n\n", cas);  */        }    }    return 0;}




原创粉丝点击