文章目录
传送门
24题中的第7题,本题为最大权闭合子图问题
思路
本题输入比较麻烦
还有一个是输出,被割的部分dis[i]一定为0,则dis[i]>0,就是要选择的。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
const int N=6e4+5;
struct node
{
int v,cap,to;
}s[N];
bool flag;
int sum;
int n,m;
int cnt,head[N],dis[N];
int pre[N];
int f[N];
int a,t;///??μ?
void add(int u,int v,int cap)
{
s[cnt].v=v;
s[cnt].cap=cap;
s[cnt].to=head[u];
head[u]=cnt++;
s[cnt].v=u;
s[cnt].cap=0;
s[cnt].to=head[v];
head[v]=cnt++;
}
int read()
{
char ch=' ';int res=0;
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
if(ch=='\n') flag=1;
return res;
}
bool bfs()
{
queue<int>q;
memset(dis,0,sizeof(dis));
dis[a]=1;
q.push(a);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int e=head[u];~e;e=s[e].to)
{
int v=s[e].v,cap=s[e].cap;
if(!dis[v]&&cap>0)
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[t]!=0;
}
int dfs(int u,int flow)
{
int mm;
if(u==t)
return flow;
for(int e=head[u];~e;e=s[e].to)
{
int v=s[e].v,cap=s[e].cap;
if(cap>0&&dis[v]==dis[u]+1&&(mm=dfs(v,min(cap,flow))))
{
if(u!=a) pre[v]=1,f[u]=1;
s[e].cap-=mm;
s[e^1].cap+=mm;
return mm;
}
}
dis[u]=-1;
return 0;
}
int dinic()
{
int ans=0,tf;
while(bfs())
{
while(tf=dfs(a,inf))//0±íê??′μ?
{
//printf("%d*\n",tf);
ans+=tf;
}
}
return ans;
}
void init()///3?ê??ˉ
{
cnt=0;
memset(head,-1,sizeof(head));
}
int main()
{
init();
m=read();n=read();
// cout<<m<<" "<<n<<endl;
int x;
a=0;t=n+m+1;
for(int i=1;i<=m;i++)
{
x=read();
sum+=x;
add(a,i,x);
flag=0;
while(!flag)
{
x=read();
add(i,m+x,inf);
}
}
for(int i=1;i<=n;i++)
{
x=read();
add(i+m,t,x);
}
int num=dinic();
for(int i=1;i<=m;i++)
if(dis[i]>0) cout<<i<<" ";
cout<<endl;
for(int i=1;i<=n;i++)
if(dis[i+m]>0) cout<<i<<" ";
cout<<endl;
printf("%d\n",sum-num);
return 0;
}