啊啊全局最小割?
看了一天没看懂
考虑一个最小割,把原图分成两半(废话
左边取一个点为S,右边去一个点为T,跑出来的最小割一定是答案(废话
于是取1为S,随机T,1000组,保证不重复,随机数据随便过
但是有卡点,3000个点被分成了2999+1或2998+2
这两种情况都是可以预处理的
当2997+3时有三个点随机到一个就行,1000次,A掉的概率有,大概每个点70%
想想卡点不多(2999+1,2998+2为主),随机至上(笑),反正过了
#include <ctime>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;++j)
#define red(j,k,l) for (int j=k;j>=l;--j)
#define N 3005
#define M 100005*2
#define inf 1000000007
#define min(a,b) (((a)<(b))?(a):(b))
using namespace std;
int n,m,a[M],b[M],c[M],d[M],e[M],pos;
struct Dinic{
int st[N],to[M],ne[M],mx[M],fl[M],deep[N],que[N],cur[N],S,T,cnt;
void add(int k,int l,int poi){
to[++cnt]=l;
mx[cnt]=poi;
ne[cnt]=st[k];
st[k]=cnt;
fl[cnt]=0;
//if (poi>0) cout<<k<<' '<<l<<' '<<poi<<endl;
}
void set(){
S=1,T=d[++pos];
cnt=1;rep(i,1,n) st[i]=0;
rep(i,1,m) add(a[i],b[i],c[i]),add(b[i],a[i],c[i]);
}
bool bfs(){
int head=0,tail=1;
que[1]=S;memset(deep,0,sizeof(deep));
deep[S]=1;
while (head!=tail){
int x=que[++head];
for (int i=st[x];i;i=ne[i])
if (deep[to[i]]==0&&fl[i]!=mx[i]){
deep[to[i]]=deep[x]+1;
que[++tail]=to[i];
if (to[i]==T) return 1;
}
}
return deep[T]>0;
}
int dfs(int k,int re){
if (k==T||re==0) return re;
int flow=0,f;
for (int i=cur[k];i;cur[k]=i=ne[i])
if (deep[to[i]]==deep[k]+1&&(f=dfs(to[i],min(re,mx[i]-fl[i])))>0){
//printf("--!--%d %d\n",k,f);
fl[i]+=f;fl[i^1]-=f;
flow+=f;re-=f;
if (!re) return flow;
}
if (re) deep[k]=-1;
return flow;
}
int maxflow(){
int flow=0;
while (bfs()){
//puts("ok");
rep(i,1,n) cur[i]=st[i]; //зЂвт
flow+=dfs(S,inf);
}
//printf("----%d\n",flow);
return flow;
}
} F;
int main(){
srand(time(0));
while (scanf("%d%d",&n,&m)!=EOF){
for (int i=1;i<n;i++) d[i]=i+1;
random_shuffle(d+1,d+n);
pos=0;
memset(e,0,sizeof(e));
rep(i,1,m)
scanf("%d%d%d",a+i,b+i,c+i),e[a[i]]+=c[i],e[b[i]]+=c[i];
int ans=inf,pi;
rep(i,1,n) ans=min(ans,e[i]);
rep(i,1,m) ans=min(ans,e[a[i]]+e[b[i]]-2*c[i]);
rep(i,1,min(500,n-1)) F.set(),pi=F.maxflow(),ans=min(ans,pi);
printf("%d\n",ans);
}
}