求一个割集 使得割集的平均边权最小
具体的解答 请看Amber论文《最小割模型在信息学竞赛中的应用》
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#define MEM(a,x) memset(a,x,sizeof a)
#define eps 1e-8
#define MOD 10009
#define MAXN 100010
#define MAXM 50100
#define INF 99999999
#define ll __int64
#define bug cout<<"here"<<endl
#define fread freopen("ceshi.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
using namespace std;
struct Edge
{
int to,next;
double flow,cap;
}edge[MAXM];
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol=0;
MEM(head,-1);
}
void addedge(int u,int v,double w,double rw)
{
edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
edge[tol].flow=0; head[u]=tol++;
edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
edge[tol].flow=0; head[v]=tol++;
}
double sap(int start,int ed,int N)
{
MEM(gap,0);
MEM(dep,0);
memcpy(cur,head,sizeof(head));
// for(int i=start;i<=ed;i++)
// cur[i]=head[i];
int u=start;
pre[u]=-1;
gap[0]=N;
double ans=0;
while(dep[start]<N)
{
if(u==ed)
{
double Min=INF*1.0;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=0;
int v;
for(int i=cur[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if((edge[i].cap-edge[i].flow)>eps&&dep[v]+1==dep[u])
{
flag=1;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v; continue;
}
int Min=N;
for(int i=head[u];i!=-1;i=edge[i].next)
if((edge[i].cap-edge[i].flow)>eps&&dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start) u=edge[pre[u]^1].to;
}
return ans;
}
struct point
{
int u,v;
double w;
}po[MAXM];
int vis[MAXN];
void dfs(int u)
{
vis[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap-edge[i].flow>eps&&!vis[edge[i].to])
dfs(edge[i].to);
}
int main()
{
// fread;
int n,m;
int cs=0;
while(scanf("%d%d",&n,&m)!=EOF)
{
double st=10000010,ed=0.0;
for(int i=0;i<m;i++)
{
scanf("%d%d%lf",&po[i].u,&po[i].v,&po[i].w);
st=min(st,po[i].w);
ed=max(ed,po[i].w);
}
// double st=0.0,ed=10000010;
double mid;
double flow;
while(ed-st>eps)
{
init();
mid=(ed+st)/2.0;
flow=0;
for(int i=0;i<m;i++)
{
if(po[i].w<=mid) flow+=po[i].w-mid;
else addedge(po[i].u,po[i].v,po[i].w-mid,po[i].w-mid);
}
flow+=sap(1,n,n);
if(flow>0) st=mid;
else ed=mid;
}
init();
for(int i=0;i<m;i++)
{
if(po[i].w<=ed) continue;
addedge(po[i].u,po[i].v,po[i].w-ed,po[i].w-ed);
}
sap(1,n,n);
MEM(vis,0);
dfs(1);
vector<int> ans;
for(int i=0;i<m;i++)
{
if((po[i].w<=ed)||(vis[po[i].u]&&!vis[po[i].v])||(!vis[po[i].u]&&vis[po[i].v]))
ans.push_back(i+1);
}
int num=ans.size();
if(cs) puts("");
else cs=1;
printf("%d\n",num);
for(int i=0;i<num;i++)
{
if(i) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
ans.clear();
}
return 0;
}