usaco Pollutant Control
第一问是求最小割。第二问求最小割中集合中边最少的集合的大小。
第三问求集合中边最少且字典序最小的边的下标。
第一问直接求最大流就能解,第二问将原来的边的容量都改为1,求出来的最大流就是元素最少的一个最小割的大小。
将容量都改为1之后,直接枚举每个边和前面已经找到的边在同一个集合中,是的话输出边的下标。
/*
ID: modengd1
PROG: milk6
LANG: C++
*/
#include <iostream>
#include <memory.h>
#include <stdio.h>
#include <vector>
#include <queue>
using namespace std;
int N,M;
int level[33];
int input[33][33];
int inputC[33][33];
struct Edge
{
int x,y,w;
};
vector<Edge> Edges;
void BFS(int s)
{
memset(level,-1,sizeof(level));
level[s]=0;
queue<int> Q;
Q.push(s);
while(!Q.empty())
{
int now=Q.front();Q.pop();
for(int i=1;i<=N;i++)
{
if(input[now][i]&&level[i]<0)
{
level[i]=level[now]+1;
Q.push(i);
}
}
}
}
int DFS(int s,int t,int f)
{
if(s==t)
return f;
for(int i=1;i<=N;i++)
{
if(input[s][i]&&level[i]==level[s]+1)
{
int d=DFS(i,t,min(f,input[s][i]));
if(d>0)
{
input[s][i]-=d;
input[i][s]+=d;
return d;
}
}
}
return 0;
}
int max_flow(int s,int t)
{
int flow=0;
while(true)
{
BFS(s);
if(level[t]<0)
return flow;
int f;
while((f=DFS(s,t,0x7fffffff))>0)
{
flow+=f;
}
}
}
int main()
{
freopen("milk6.in","r",stdin);
freopen("milk6.out","w",stdout);
scanf("%d%d",&N,&M);
memset(input,0,sizeof(input));
for(int i=0;i<M;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
Edges.push_back((Edge){a,b,c});
input[a][b]+=c;
}
int ans1=max_flow(1,N);
cout<<ans1;
for(int i=0;i<Edges.size();i++)
{
input[Edges[i].x][Edges[i].y]+=1;
}
memcpy(inputC,input,sizeof(inputC));
int ans2=max_flow(1, N);
cout<<' '<<ans2<<endl;
for(int i=0;i<Edges.size();i++)
{
memcpy(input,inputC,sizeof(input));
input[Edges[i].x][Edges[i].y]-=1;
memcpy(inputC,input,sizeof(inputC));
int f=max_flow(1,N);
if(f<ans2)
{
cout<<i+1<<endl;
ans2=f;
}
else {
inputC[Edges[i].x][Edges[i].y]+=1;
}
}
}
浙公网安备 33010602011771号