[关键字]:图论 网络流
[题目大意]:在一个网络里求一个割,而且要保证(1)、容量最小(就是最小割)。(2)、满足医(1)的情况小边最少。(3)、满足(1)(2)情况下边的字典序最小。
//=========================================================================================================================================
[分析]:第一二问可以将每个边的权值c改成C=c*(M+1)+1,然后在求最小割maxf。第一问答案就是maxf/(M+1)第二问答案就是maxf mod (M+1),因为此时的最小割容量Cmin=cmin*(M+1)+min(sum 1),cmin就是原来的最小割, 因为没有一个1就代表有一条边,所以min(sum 1)代表最小边数。第三问比较麻烦,首先如果一条边在最小割里那删掉它后,最大流流量回减少这条边的权值。再者如果一条边在最小割里那么删掉这条边后原先包含这条边的最小割仍旧是最小割,所以不用担心最小割出错。这样可以用枚举的方法从小到大枚举每一条边判断是否属于最小割,然后删掉再继续重复。
http://hi.baidu.com/mengyun1993/blog/item/c30d193c9a85932870cf6cda.html Orz!!!
[代码]:
View Code
/*
ID:procedure2
PROB:milk6
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
int x,y;
long long d;
}e[1002];
int N,M,tot,INF,S,T;
int num[33],h[33];
long long c[33][33],c1[33][33],c2[33][33];
void Init()
{
scanf("%d%d",&N,&M);
for (int i=1;i<=M;i++)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
if (d)
{
e[++tot].x=x,e[tot].y=y;
e[tot].d=(long long)(d*1001)+(long long)(1);
c[x][y]+=e[tot].d;
INF+=e[tot].d;
}
}
S=1,T=N;
//printf("%d\n",tot);
//for (int i=1;i<=tot;i++) printf("%d %d %d\n",e[i].x,e[i].y,e[i].d);
}
long long Find(int u,long long flow)
{
if (u==T) return flow;
long long temp=flow;
int pos=N-1;
for (int i=1;i<=N;i++)
{
if (h[u]==h[i]+1 && c1[u][i])
{
long long f=Find(i,min(c1[u][i],temp));
temp-=f;
c1[u][i]-=f;
c1[i][u]+=f;
//cout<<u<<' '<<i<<' '<<f<<endl;
if (h[S]==N || !temp) return flow-temp;
}
if (c1[u][i] && pos>h[i]) pos=h[i];
}
if (temp==flow)
{
num[h[u]]--;
if (!num[h[u]]) h[S]=N;
else
{
h[u]=pos+1;
//printf("%d %d\n",u,h[u]);
num[h[u]]++;
}
}
//printf("%d %d %d\n",u,h[u],pos);
return flow-temp;
}
long long SAP()
{
memcpy(c1,c,sizeof(c));
memset(h,0,sizeof(h));
memset(num,0,sizeof(num));
num[0]=N;
/*for (int i=1;i<=N;i++)
for (int j=1;j<=N;j++)
if (c1[i][j]) printf("%d %d %lld\n",i,j,c1[i][j]);*/
long long ans=0;
while (h[S]<N) ans+=Find(S,INF);
return ans;
}
void Solve()
{
long long maxf=SAP();
//printf("%ld\n",maxf);
printf("%ld ",maxf/1001);
printf("%ld\n",maxf%1001);
memcpy(c2,c1,sizeof(c1));
for (int i=1;i<=tot;i++)
if (!c2[e[i].x][e[i].y])
{
c[e[i].x][e[i].y]-=e[i].d;
long long t=SAP();
//printf("%d %d\n",maxf,t);
if (maxf-t==e[i].d)
{
printf("%d\n",i);
maxf=t;
memcpy(c2,c1,sizeof(c1));
}
else c[e[i].x][e[i].y]+=e[i].d;
//printf("%d\n",c2[e[i].x][e[i].y]);
}
}
int main()
{
freopen("milk6.in","r",stdin);
freopen("milk6.out","w",stdout);
Init();
Solve();
return 0;
}