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