「伪模板」主席树
果然,题目显示什么算法就绝对和什么算法没关系...
这个题建图挺显然的吧....
这里重新思考一下建图的意义:源点向某个点连边表示某个点本来就有的属性,某个点向汇点连边,表示这个点向答案能造成的贡献和限制.
之后就是两侧的点连边...
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=210,M=N*N*2,INF=1e9; int link[N],tot=1,n,m,id1[N],id2[N],blood1[N],blood2[N],s,t; int current[N],d[N]; struct edge{int y,v,next;}a[M]; char c[10]; inline int read() { int x=0,ff=1; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*ff; } inline void add(int x,int y,int v) { a[++tot].y=y;a[tot].v=v;a[tot].next=link[x];link[x]=tot; a[++tot].y=x;a[tot].v=0;a[tot].next=link[y];link[y]=tot; } inline void init() { for(int i=1;i<=n;++i) { scanf("%s",c); if(c[0]=='W') id1[i]=1; else if(c[0]=='J') id1[i]=2; else if(c[0]=='E') id1[i]=3; else if(c[0]=='Y') id1[i]=4; else if(c[0]=='H') id1[i]=5; } for(int i=1;i<=n;++i) { scanf("%s",c); if(c[0]=='W') id2[i]=1; else if(c[0]=='J') id2[i]=2; else if(c[0]=='E') id2[i]=3; else if(c[0]=='Y') id2[i]=4; else if(c[0]=='H') id2[i]=5; } for(int i=1;i<=n;++i) blood1[i]=read(); for(int i=1;i<=n;++i) blood2[i]=read(); } inline void make_chart() { s=0;t=n<<1|1; int cnt=0; for(int i=1;i<=n;++i) if(id1[i]==4) cnt++; for(int i=1;i<=n;++i) if(id1[i]==2) blood1[i]+=cnt; for(int i=1;i<=n;++i) add(s,i,blood1[i]); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { if(id1[i]==1&&(id2[j]==3||id2[j]==4)) add(i,j+n,1); else if(id1[i]==2&&(id2[j]==1||id2[j]==5)) add(i,j+n,1); else if(id1[i]==3&&(id2[j]==2||id2[j]==4)) add(i,j+n,1); else if(id1[i]==4&&(id2[j]==2||id2[j]==5)) add(i,j+n,1); else if(id1[i]==5&&(id2[j]==3||id2[j]==1)) add(i,j+n,1); } cnt=0; for(int i=1;i<=n;++i) if(id2[i]==4) cnt++; for(int i=1;i<=n;++i) if(id2[i]==2) blood2[i]+=cnt; for(int i=1;i<=n;++i) add(i+n,t,blood2[i]); } inline bool bfs() { queue<int>q;q.push(s); memset(d,0,sizeof(d)); memcpy(current,link,sizeof(current)); d[s]=1; while(!q.empty()) { int x=q.front();q.pop(); for(int i=link[x];i;i=a[i].next) { int y=a[i].y; if(d[y]||!a[i].v) continue; d[y]=d[x]+1; q.push(y); if(y==t) return true; } } return false; } inline int dinic(int x,int flow) { if(x==t) return flow; int rest=flow,k; for(int i=current[x];i&&rest;i=a[i].next) { current[x]=i; int y=a[i].y; if(d[y]==d[x]+1&&a[i].v) { k=dinic(y,min(a[i].v,rest)); if(!k) d[y]=0; a[i].v-=k; a[i^1].v+=k; rest-=k; } } return flow-rest; } int main() { freopen("1.in","r",stdin); n=read();m=read(); init(); make_chart(); int maxflow=0,flow; while(bfs()) while(flow=dinic(s,INF)) maxflow+=flow; printf("%d",maxflow>m?m:maxflow); return 0; }