题解:
暴力枚举
然后网络流
代码:
#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; }