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;
		}
	}
}

 

posted on 2015-10-10 16:53  insaneman  阅读(457)  评论(0)    收藏  举报

导航