球队有至多20个人,派11个人出战。每个人出战每个位置会有一定的战斗力,有的人不能出战某些位置,一共有4个位置。某些人和某些人如果同时在场的话会让战斗力上升或下降。现在已知每个位置需要的人数,求最高战斗力。
枚举所有情况,然后费用流判断是否可行,以及最大费用。
每当决定选一个人的时候,就把这个流量流过去,不再选他的时候再把流量退回来。复杂度为C(20,11)*m,m为图中的边数。边数不会超过100条,C(20,11)为1.7*10^5左右..
而且事实证明...因为SPFA的时候记录路径..常数好像比较大..于是差点TLE..压线飘过了...
题解说的不是这样..题解说用dp计算是否可行及最大费用,状态不会超过300多..因为常数比较小..所以比较快..
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
const int MAXINT=(1<<30);
const int N=30;
const int M=200;
struct Node {
int fe,curCost,fromEdge;
bool inque;
};
struct Edge {
int f,t,ne,c;
};
Node a[N];
Edge b[M*2];
int t,nd,p,cost;
void clear(int nn,int tt) {
nd=nn;t=tt;
for (int i=0;i<nd;i++) a[i].fe=-1;
p=0; cost=0;
}
void putedge(int x,int y,int f,int c) {
//printf("%d %d %d %d\n",x,y,f,c);
b[p].ne=a[x].fe; b[p].t=y; b[p].f=f; b[p].c=c; a[x].fe=p++;
b[p].ne=a[y].fe; b[p].t=x; b[p].f=0; b[p].c=-c; a[y].fe=p++;
}
int edg[20][100];
int edgSize[20];
bool spfa(int s) {
static int d[N];
int i,p,q,j;
for (i=0;i<nd;i++) {
a[i].curCost=-MAXINT;
a[i].fromEdge=-1;
a[i].inque=false;
}
p=q=0;
d[q++]=s;
a[s].inque=true;
a[s].curCost=0;
while (p!=q) {
i=d[p];
for (j=a[i].fe;j!=-1;j=b[j].ne) {
Node &tmp=a[b[j].t];
if (b[j].f>0&&b[j].c+a[i].curCost>tmp.curCost) {
tmp.curCost=a[i].curCost+b[j].c;
tmp.fromEdge=j;
if (tmp.inque==false) {
tmp.inque=true;
d[q]=b[j].t;
q++;
if (q>N) q-=N;
}
}
}
a[i].inque=false;
p++;
if (p>N) p-=N;
}
if (a[t].curCost==-MAXINT) return false;
for (i=t;i!=s;) {
int tmp=a[i].fromEdge;
b[tmp].f--;
b[tmp^1].f++;
cost+=b[tmp].c;
edg[s][edgSize[s]++]=tmp;
i=b[tmp^1].t;
}
return true;
}
void decflow(int i) {
for (int j=0;j<edgSize[i];j++) {
int tmp=edg[i][j];
b[tmp].f++;
b[tmp^1].f--;
}
edgSize[i]=0;
}
int n,ans;
int benefitP[20][40];
int benefitV[20][40];
int benefitSize[20];
bool choose[20];
void readData() {
static map<int,int> c;
int i,j,x,y,m;
char str[10];
scanf("%d",&n);
clear(n+5,n+4);
for (i=0;i<n;i++) {
choose[i]=false;
edgSize[i]=0;
benefitSize[i]=0;
}
c.clear();
for (i=0;i<n;i++) {
scanf("%d",&x);
c[x]=i;
scanf("%d",&m);
for (j=0;j<m;j++) {
scanf("%s%d%d",str,&x,&y);
//printf("%s %d %d\n",str,x,y);
x=(x+1000)*40000+y+1000;
if (str[0]=='G') putedge(i,n,1,x);
else if (str[0]=='D') putedge(i,n+1,1,x);
else if (str[0]=='M') putedge(i,n+2,1,x);
else if (str[0]=='S') putedge(i,n+3,1,x);
}
}
scanf("%d",&m);
for (i=0;i<m;i++) {
scanf("%d%d%s%d",&x,&y,str,&j);
//printf("%d %d %s %d\n",x,y,str,j);
x=c[x];y=c[y];
if (x<y) swap(x,y);
if (str[0]=='D') j=-j;
int &tmp=benefitSize[x];
benefitP[x][tmp]=y;
benefitV[x][tmp]=j*40000;
tmp++;
}
scanf("%d-%d-%d",&x,&y,&j);
//printf("%d %d %d\n",x,y,j);
putedge(n,t,1,0);
putedge(n+1,t,x,0);
putedge(n+2,t,y,0);
putedge(n+3,t,j,0);
ans=-MAXINT;
}
void findAns(int i,int res) {
if (res==0) {
if (cost>ans) ans=cost;
} else {
//for (int j=0;j<n;j++) if (choose[j]) printf("%d ",j);
//printf("--%d %d %d\n",i,res,n);
for (;i+res<=n;i++) {
choose[i]=true;
int tmp=benefitSize[i];
int tmpcost=cost;
for (int j=0;j<tmp;j++) if (choose[benefitP[i][j]]) cost+=benefitV[i][j];
if (spfa(i))
findAns(i+1,res-1);
decflow(i);
choose[i]=false;
cost=tmpcost;
}
}
}
int main() {
int t;
scanf("%d",&t);
while (t--) {
readData();
findAns(0,11);
if (ans==-MAXINT) printf("Poor Manager!\n");
else printf("%d %d\n",ans/40000-11000,ans%40000-11000);
}
return 0;
}