一道网络流的题,求出最大流,然后求出最小割的最小的边数,还要输出最小割字典序最小的一组;
正儿八经的写的第一道网络流的题目吧,进步蛮大的。
基本思路是,先求出最大流,然后枚举每一条边,删除这条边后求最大流,如果求出的最大流加上被删除变的容量等于没有删除任何边的最大流,就说明这条边属于最小割,输出之,注意输出的时候记录下已经输出了多少条边了,输完了就退出,不然会多输出,至于为什么可以先知道最小割有多少条边,参考nocow题解那个c×1001+1,
by the way ,如果看不到数据的话,真不知道要debug多久。能看到数据的话就得记住错在了什么地方,下次看不到数据的时候才有debug的方向.
注意:有重边,容量用Long long 存储。
#include<iostream>
#include<fstream>
#include<vector>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define maxn 40
#define maxm 1200
#define M(a) memset((a),0,sizeof((a)))
#define zout cout
using namespace std;
ifstream fin("milk6.in");
ofstream fout("milk6.out");
struct Edge
{
long long from,to,cap,flow,num,ag;
};
bool vis[maxn];
int d[maxn];
vector<Edge> edge;
int cur[maxn];
vector<int> g[maxn];
int n,m,s,t;
bool init()
{
if(fin>>n>>m)
{
edge.clear();
int x,y,w;
for(int i=1;i<=m;i++)
{
fin>>x>>y>>w;
w=w*1001+1;
edge.push_back((Edge){
x,y,w,0,i,0
});
edge.push_back((Edge){
y,x,0,0,0,0
});
int ln=edge.size();
g[x].push_back(ln-2);
g[y].push_back(ln-1);
}
s=1;t=n;
return true;
}
return false;
}
bool bfs()
{
M(vis);
queue<int> q;
d[s]=0;
q.push(s);
vis[s]=1;
while(!q.empty())
{
int u=q.front();q.pop();
int ln=g[u].size();
for(int i=0;i<ln;i++)
{
Edge &e =edge[g[u][i]];
if(e.ag)continue;
if(!vis[e.to]&&e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[u]+1;
q.push(e.to);
}
}
}
return vis[t];
}
long long dfs(int u,long long a)
{
if(u==t||a==0)return a;
long long flow=0,f;
for(int & i= cur[u];i<g[u].size();i++)
{
Edge &e = edge[g[u][i]];
if(e.ag)continue;
if(d[u]+1==d[e.to])
{
if(a==-1)
{
f=dfs(e.to,e.cap-e.flow);
}
else
{
f=dfs(e.to,min(a,e.cap-e.flow));
}
if(f>0)
{
flow+=f;
e.flow+=f;
edge[g[u][i]^1].flow-=f;
if(a>0)
a-=f;
}
}
}
return flow;
}
long long cal_flow()
{
long long flow=0;
int ln=edge.size();
for(int i=0;i<ln;i++)
edge[i].flow=0;
while(bfs())
{
M(cur);
flow+=dfs(s,-1);
}
return flow;
}
void slove()
{
long long max_flow=cal_flow();
long long temp_flow;
zout<<max_flow/1001<<" "<<max_flow%1001<<endl;
int ln=edge.size();
int calu=max_flow%1001;
for(int i=0;calu&&i<ln;i++)
{
Edge &e = edge[i];
if(e.num)
{
edge[i].ag=1;
edge[i^1].ag=1;
temp_flow=cal_flow();
if(temp_flow+e.cap==max_flow)
{
calu--;
zout<<e.num<<endl;
}
edge[i].ag=0;
edge[i^1].ag=0;
}
}
}
int main()
{
while(init())
slove();
return 0;
}