添加超级源和超级汇,然后将s和正权边相连,负权边和t相连,这时候对应的每一个割对应着一种方案,然后最小割即可
胡伯涛《最小割模型在信息学竞赛中的应用》
论文如上orzzzzzz,不过他提出来的超级神的40s变成0.71s的优化会慢成原来的两倍23333333333333333
还有就是千万不能先把ne=0,然后在得到反边的时候直接+1,会挂的orzzzzzz然而不强制奇数直接+1为什么会错呢还没想明白
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,x) for(int i=last[x];i!=0;i=e[i].next)
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
#define N 6005
#define M 50005
#define inf 0x7fffffff
struct edge
{
int y,f,next;
}e[M*10];
int last[N*10],ne=1;
int h[N*10];
int n,m;
void add(int x,int y,int w)
{
e[++ne].y=y;e[ne].f=w;e[ne].next=last[x];last[x]=ne;
}
void add2(int u,int v,int w)
{
add(u,v,w);add(v,u,0);
}
int q[N*10];
bool bfs(int s,int t)
{
memset(h,0,sizeof(h));
int head=0,tt=1;
q[1]=s;h[s]=1;
while(head<tt)
{
int now=q[++head];
if(now==t)return 1;
efo(i,now)
if(h[e[i].y]==0&&e[i].f)
{
// cout<<e[i].y<<' '<<e[i].f<<endl;
q[++tt]=e[i].y;
h[e[i].y]=h[now]+1;
}
}
return 0;
}
int dfs(int x,int maxf,int t)
{
// cout<<x<<' '<<maxf<<' '<<t<<endl;
if(x==t) return maxf;
int ret=0,f=0;
efo(i,x)
if(e[i].f!=0&&h[e[i].y]==h[x]+1)
{
f=dfs(e[i].y,min(maxf-ret,e[i].f),t);
// cout<<e[i].y<<' '<<f<<endl;
e[i].f-=f;
e[i^1].f+=f;
ret+=f;
if(ret==maxf)return ret;
}
return ret;
}
int dinic(int s,int t)
{
int ans=0;
// cout<<"begin"<<endl;
while(bfs(s,t))ans+=dfs(s,inf,t);
return ans;
}
int main()
{
n=read(),m=read();
fo(i,1,n)
{
int x=read();
add2(0,i,x);
}
int sum=0;
fo(i,1,m)
{
int x=read(),y=read(),w=read();
add2(x,n+i,inf);
add2(y,n+i,inf);
add2(n+i,n+m+1,w);
sum+=w;
}
int ans=dinic(0,n+m+1);
cout<<sum-ans<<endl;
return 0;
}