hdu6214—Smallest Minimum Cut(最小割的最少割边)

来源:互联网 发布:睡别人女朋友 知乎 编辑:程序博客网 时间:2024/06/04 18:56

题目链接:传送门

Smallest Minimum Cut

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)
Total Submission(s): 947    Accepted Submission(s): 368


Problem Description
Consider a network G=(V,E) with source s and sink t. An s-t cut is a partition of nodes set V into two parts such that s and t belong to different parts. The cut set is the subset of E with all edges connecting nodes in different parts. A minimum cut is the one whose cut set has the minimum summation of capacities. The size of a cut is the number of edges in the cut set. Please calculate the smallest size of all minimum cuts.
 

Input
The input contains several test cases and the first line is the total number of cases T (1T300).
Each case describes a network G, and the first line contains two integers n (2n200) and m (0m1000) indicating the sizes of nodes and edges. All nodes in the network are labelled from 1 to n.
The second line contains two different integers s and t (1s,tn) corresponding to the source and sink.
Each of the next m lines contains three integers u,v and w (1w255) describing a directed edge from node u to v with capacity w.
 

Output
For each test case, output the smallest size of all minimum cuts in a line.
 

Sample Input
24 51 41 2 31 3 12 3 12 4 13 4 24 51 41 2 31 3 12 3 12 4 13 4 3
 

Sample Output
23


解题思路:对于每条边的权值做个简单的处理:w = c*t+1,c为初始边权,t为一个比较大的数,此时求图中的最小割,求出的一定是边数最少的。最后最少的边数是:maxflow%t。


#include <cstdio>  #include <algorithm>  #include <queue>  #include <iostream>  using namespace std;  const int N = 420;  const int M = 40900;  const int mod = 1000;//边的结构  struct edge_t{  int node;  int c;//c为容量  edge_t* next;  edge_t* redge;//指向反向边  }Edge[M*2];  int ECnt;  //图的邻接表  edge_t* Ver[N];  void init(){  ECnt = 0;  fill(Ver,Ver+N,(edge_t*)0);  }  //生成双向边  void mkEdge(int a,int b,int c){  int t1 = ECnt++;  int t2 = ECnt++;  Edge[t1].node = b;  Edge[t1].c = c;  Edge[t1].next = Ver[a];  Edge[t1].redge = Edge + t2;  Ver[a] = Edge + t1;  Edge[t2].node = a;  Edge[t2].c = 0;  Edge[t2].next = Ver[b];  Edge[t2].redge = Edge + t1;  Ver[b] = Edge + t2;  }  int L[N];//层次图  //建立残留网络从源s到汇t的层次图  bool bfs(int s,int t){  fill(L,L+N,-1);  queue<int>q;  q.push(s);  L[s] = 0;  while( !q.empty() ){  int u = q.front();  q.pop();  //寻找还有残量的边  for(edge_t*p=Ver[u];p;p=p->next){  if ( p->c <= 0 ) continue;  int v = p->node;  if ( -1 != L[v] ) continue;  q.push(v);  L[v] = L[u] + 1;  }  }  return -1 != L[t];  }  int dfs(int u,int e,int cf){  if ( u == e ) return cf;  int tf = 0;  //tf记录u往下一层的总可行流量  for(edge_t*p=Ver[u];p;p=p->next){  int v = p->node;  int c = p->c;  if ( L[u] + 1 == L[v] && c > 0 && cf > tf ){  int f = dfs(v,e,min(c,cf-tf));  if ( 0 == f ) continue;  p->c -= f;//正向边减去可行流量  p->redge->c += f;//反向边加上  tf += f;  }  }  if ( 0 == tf ) L[u] = -1;//修改层次图  return tf;  }  //Dinic算法,s为源,t为汇  int Dinic(int s,int t){  int ret = 0;  while( bfs(s,t) ){//第一步建立分层图  int ans;  //第二步在分层图上查找一条增广路径的可行流量  while( ans = dfs(s,t,INT_MAX) )  ret += ans;  }  return ret;  }  int cost[N];  void Build( int m )  {  int a,b,c;for( int i = 0 ; i < m ; ++i ){scanf("%d%d%d",&a,&b,&c);mkEdge(a,b,c*mod+1);}}  int main()  {   int T; scanf("%d",&T); while(T--){ init(); int n,m,s,t; scanf("%d%d%d%d",&n,&m,&s,&t); Build(m); int ans = Dinic(s,t); printf("%d\n",ans%mod); }return 0;  }  


阅读全文
0 0