hdu4309

题解:

暴力枚举

然后网络流

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int E=30000,V=1102,inf=0xffff;
struct Edge{int u,v,c,next;}edge[E];
int a,bb,c,d,p[V],r,b,t,n,m,cnt,cou,dist[V],head[V],que[V],fb[12],sta[V];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
}
void jb(int u,int v,int c)
{
    edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c;
    edge[cnt].next=head[u];head[u]=cnt++;
    edge[cnt].u=v;edge[cnt].v=u;edge[cnt].c=0;
    edge[cnt].next=head[v];head[v]=cnt++;
}
int dinic(int s,int t)
{
    int ans=0;
    while(1)
     {
        int left,right,u,v;
        memset(dist,-1,sizeof(dist));
        left=right=0;
        que[right++]=s;
        dist[s]=0;
        while (left<right)
         {
            u=que[left++];
            for (int k=head[u];k!=-1;k=edge[k].next)
             {
                u=edge[k].u;
                v=edge[k].v;
                if (edge[k].c>0 && dist[v]==-1)
                 {
                    dist[v]=dist[u]+1;
                    que[right++]=v;
                    if(v==t)
                     {
                        left=right;
                        break;
                     }
                 }
             }
         }
        if (dist[t]==-1) break;
        int top=0,now=s;
        while (1)
         {
            if (now!=t)
             {
                int k;
                for (k=head[now];k!=-1;k=edge[k].next)
                 if (edge[k].c>0&&dist[edge[k].u]+1==dist[edge[k].v]) break;
                if (k!=-1)
                 {
                    sta[top++]=k;
                    now=edge[k].v;
                 }
                else
                 {
                    if (top==0) break;
                    dist[edge[sta[--top]].v]=-1;
                    now=edge[sta[top]].u;
                 }
             }
            else
             {
                int flow=inf,ebreak;
                for (int i=0;i<top;i++)
                 if (flow>edge[sta[i]].c)
                  {
                    flow=edge[sta[i]].c;
                    ebreak=i;
                  }
                ans+=flow;
                for (int i=0;i<top;i++)
                 {
                    edge[sta[i]].c-=flow;
                    edge[sta[i]^1].c+=flow;
                 }
                now=edge[sta[ebreak]].u;
                top=ebreak;
             }
         }
     }
    return ans;
}
struct T{int u,v,c;}road[E],bridge[E],tunnel[E];
struct R{int num,cost;}res[E];
void build()
{
    init();
    for (int i=1;i<=n;i++)jb(0,i,p[i]);
    for (int i=0;i<r;i++)jb(road[i].u,road[i].v,inf);
    for (int i=0;i<t;i++)
     {
        jb(tunnel[i].u,n+i+1,inf);
        jb(n+i+1,tunnel[i].v,inf);
        jb(n+i+1,n+t+1,tunnel[i].c);
     }
}
void dfs(int s)
{
    if (s==b)
     {
        int sum=0;
        build();
        for (int i=0;i<b;i++)
         {
            if (fb[i]==0)
             {
                jb(bridge[i].u,bridge[i].v,1);
                sum+=0;
             }
            else
             {
                jb(bridge[i].u,bridge[i].v,inf);
                sum+=bridge[i].c;
             }
         }
        res[cou].num=dinic(0,n+t+1);
        res[cou++].cost=sum;
        return ;
     }
    fb[s]=0;
    dfs(s+1);
    fb[s]=1;
    dfs(s+1);
}
int main()
{
    while (~scanf("%d%d",&n,&m))
     {
        for (int i=1;i<=n;i++)scanf("%d",&p[i]);
        r=b=t=0;
        for (int i=1;i<=m;i++)
         {
            scanf("%d%d%d%d",&a,&bb,&c,&d);
            if (d<0)
             {
                tunnel[t].u=a;
                tunnel[t].v=bb;
                tunnel[t++].c=c;
             }
            if (d==0)
             {
                road[r].u=a;
                road[r++].v=bb;
             }
            if (d>0)
             {
                bridge[b].u=a;
                bridge[b].v=bb;
                bridge[b++].c=c;
             }
         }
        memset(fb,0,sizeof(fb));
        for (int i=0;i<5000;i++)res[i].cost=res[i].num=0;
        cou=0;dfs(0);
        int minc=inf,maxc=-1;
        for (int i=0;i<cou;i++)
         if (res[i].num>maxc)maxc=res[i].num;
        for (int i=0;i<cou;i++)
         if (res[i].num==maxc)
          if (res[i].cost<minc)minc=res[i].cost;
        if (maxc==0) puts("Poor Heaven Empire");
        else printf("%d %d
",maxc,minc);
     }
    return 0;
}
原文地址:https://www.cnblogs.com/xuanyiming/p/8366464.html