模板
最大权闭合图
如何记录路径:
最后一遍BFS传达不为-1的
原理,割与不割决定了最后的结果。
于是最后的残量网络决定了割法。
另:毒瘤读入。
#include<bits/stdc++.h>
using namespace std;
const int N=39999;
const int INF=1e9+7;
inline bool read(int &res) //遇到'\n'跳出的读入优化
{
res = 0; char ch = getchar();
while (!isdigit(ch)) { if (ch == '\n') return false; ch = getchar(); }
while (isdigit(ch)) { res = res * 10 + ch - '0'; ch = getchar(); }
if (ch == '\n') return false; else return true;
}
struct Front_star{
int u,v,w,nxt;
}e[N];
int cnt=1;
int first[N]={0};
void addedge(int u,int v,int w){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=first[u];
first[u]=cnt;
}
void add(int u,int v,int w){
addedge(u,v,w);
addedge(v,u,0);
}
int pos=0;
int n,m;
int S=0;
int T=120;
int d[3000]={0};
queue<int> q;
bool bfs(){
for(int i=S;i<=T;i++){
d[i]=-1;
}
d[S]=1;
q.push(S);
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w&&d[v]==-1){
d[v]=d[x]+1;
q.push(v);
}
}
}
return d[T]!=-1;
}
int dfs(int st,int ed,int nowdat){
int dat=0;
if(st==ed){
return nowdat;
}
for(int i=first[st];i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w&&d[v]==d[st]+1){
int now=min(nowdat-dat,e[i].w);
now=dfs(v,ed,now);
e[i].w-=now;
e[i^1].w+=now;
dat+=now;
if(nowdat==dat){
return dat;
}
}
}
if(!dat){
d[st]=-2;
}
return dat;
}
void MCMF(){
int ans=0;
while(bfs()){
ans+=dfs(S,T,INF);
// cout<<ans<<endl;
// if(ans==0)
// return;
}
for(int i=1;i<=n;i++){
if(d[i]!=-1){
printf("%d ",i);
}
}
printf("\n");
for(int i=1;i<=m;i++){
if(d[i+n]!=-1){
printf("%d ",i);
}
}
printf("\n");
printf("%d",pos-ans);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int v;
scanf("%d",&v);
add(S,i,v);
pos+=v;
int x;
while(read(x)){
// cout<<"x="<<x<<endl;
add(i,x+n,INF);
}
add(i,x+n,INF);
}
// cout<<cnt<<endl;
// for(int i=2;i<=cnt;i++){
// cout<<e[i].u<<" "<<e[i].v<<" "<<e[i].w<<endl;
// }
// cout<<"working"<<endl;
for(int i=1;i<=m;i++){
int val;
read(val);
add(i+n,T,val);
}
MCMF();
}