这个题依然是求最大闭权闭合图,在胡博涛论文中有相关介绍,我用Dinic做的~
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const long long inf=1LL<<40;
const int maxn=5010;
const int maxm=2e5;
int e,st,des,head[maxn],pnt[maxm],nxt[maxm],level[maxn];
int n,m;
long long flow[maxm];
bool vis[maxn];
queue<int> q;
void AddEdge(int u,int v,long long f)
{
pnt[e]=v;nxt[e]=head[u];flow[e]=f;head[u]=e++;
pnt[e]=u;nxt[e]=head[v];flow[e]=0;head[v]=e++;
}
bool BFS()
{
memset(level,0,sizeof(level));
q.push(st);
level[st]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i!=-1;i=nxt[i])
if(flow[i]&&!level[pnt[i]])
{
level[pnt[i]]=level[u]+1;
q.push(pnt[i]);
}
}
return level[des];
}
long long DFS(int u,long long maxf)
{
if(u==des||maxf<=0)
return max(maxf,0LL);
long long f=0;
for(int i=head[u];i!=-1;i=nxt[i])
if(flow[i]&&level[pnt[i]]==level[u]+1)
{
long long t=DFS(pnt[i],min(flow[i],maxf-f));
if(t>0)
{
flow[i]-=t;
flow[i^1]+=t;
f+=t;
if(f==maxf)
break;
}
else
level[pnt[i]]=0;
}
return f;
}
long long maxflow()
{
long long ans=0;
while(BFS())
ans+=DFS(st,inf);
return ans;
}
void dfs(int u)
{
for(int i=head[u];i!=-1;i=nxt[i])
if(flow[i]&&!vis[pnt[i]])
{
vis[pnt[i]]=1;
dfs(pnt[i]);
}
}
void solve(long long profit)
{
long long f=maxflow();
memset(vis,0,sizeof(vis));
vis[st]=1;
dfs(st);
int ans=0;
for(int i=1;i<=n;i++)
if(vis[i])
ans++;
printf("%d %I64d\n",ans,profit-f);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
e=st=0;des=n+1;
memset(head,-1,sizeof(head));
long long profit=0;
for(int i=1;i<=n;i++)
{
int val;
scanf("%d",&val);
if(val>0)
{
AddEdge(st,i,val);
profit+=val;
}
else
AddEdge(i,des,-val);
}
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
AddEdge(u,v,inf);
}
solve(profit);
}
return 0;
}