「伪模板」主席树(最大流)
这道题,在学主席树的时候就看见了,就加入了收藏计划
最近省选前,填坑,就把这道题切了
主要还是网络流
首先对网络关系处理一下,我用了一下map使它更好处理一下
建图方式:
每个人为一个点
对byx和手气君有的得膜法师进行统计
向byx每个点连边,流量为生命,如果当前节点位主席,生命值加上膜法师数量
同时对手气君的每个点也这样处理
最后对有冲突关系的双方连线,流量为1
这样乖乖的跑一下最大流就好了鸭,嘤嘤嘤
#include<bits/stdc++.h> using namespace std; const int N=1e6+7; const int INF=0x7f7f7f; //1:j 主席 2:w高人 3:HK港记 4:YYY膜法师 5:E女王 bool gx[6][6]={{0,0,0,0,0,0}, {0,0,1,1,0,0}, {0,0,0,0,1,1}, {0,0,1,0,0,1}, {0,1,0,1,0,0}, {0,1,0,0,1,0}}; int m,n,k,maxflow,cnt=1,tot,ss,t,ans,inc,mtot; int head[N],dep[N]; map<string,int> mp; string s[101][2]; bool vis[N]; struct edge { int nx,to,flow; } e[N]; void add_edge(int a,int b,int flow) { cnt++;e[cnt].nx=head[a];e[cnt].to=b;e[cnt].flow=flow;head[a]=cnt; cnt++;e[cnt].nx=head[b];e[cnt].to=a;e[cnt].flow=0;head[b]=cnt; } bool bfs(int s,int t) { queue<int> que;que.push(s); memset(dep,0,sizeof(dep));dep[s]=1; while (!que.empty()) { int x=que.front();que.pop(); for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (dep[y]==0&&e[i].flow) { dep[y]=dep[x]+1; que.push(y); } } } if (dep[t]==0) return false; else return true; } int dfs(int x,int limit,int t) { if (x==t) return limit; int used=0; for (int i=head[x];i;i=e[i].nx) { int y=e[i].to; if (dep[y]==dep[x]+1&&e[i].flow) { int di=dfs(y,min(limit-used,e[i].flow),t); if (di>0) { e[i].flow-=di; e[i^1].flow+=di; used+=di; if (used==limit) return limit; } } } if (!used) dep[x]=-2; return used; } void dinic(int s,int t) { while (bfs(s,t)) ans+=dfs(s,INF,t); } int main() { scanf("%d%d",&n,&m);ss=N-3;t=N-4; for (int i=1;i<=n;i++) cin>>s[i][0]; for (int i=1;i<=n;i++) cin>>s[i][1]; mp["J"]=1;mp["W"]=2;mp["HK"]=3;mp["YYY"]=4;mp["E"]=5; for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { int x=mp[s[i][0]],y=mp[s[j][1]]; if (gx[x][y])add_edge(i,j+n,1); } for (int i=1;i<=n;i++) if (mp[s[i][0]]==4) tot++; for (int j=1;j<=n;j++) if (mp[s[j][1]]==4) mtot++; for (int i=1;i<=n;i++) { int x;scanf("%d",&x); if (mp[s[i][0]]==1) add_edge(ss,i,x+tot); else add_edge(ss,i,x); } for (int i=1;i<=n;i++) { int x;scanf("%d",&x); if (mp[s[i][1]]==1) add_edge(i+n,t,x+mtot); else add_edge(i+n,t,x); } dinic(ss,t); printf("%d\n",min(ans,m)); return 0; }
版权声明:本文为Hale522520原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。