码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3987 求最小割条数最小

时间:2014-12-01 22:30:19      阅读:262      评论:0      收藏:0      [点我收藏+]

标签:io   os   sp   for   on   bs   代码   ad   ef   

题意:    一个人要从起点  0  到达 n-1   n个点  m条路  ,我们求最少破坏路的条数使无法 从起点到达终点。题意很明显  ,求最小割条数最少,由于最小割流量虽然固定,但是其条数却不固定,可以破坏3条路,也可以破坏4条路,他们总流量相同才会出现这种情况。

题解:由于上述的情况,他们总流量相同但是条数不同,现在我们需要改变边的容量使得条数少边才是最小割,条数多的将不会是最小割。

官方题解有两种 ,我选择的是在残余网络中进行扩充流的操作,使的两个最小割不同,残余网络中,我进行所有边流量加1的操作,在跑一遍最大流可以得出最小割的最小条数

还有一种方法是在跑最大流之前扩充流量 ,然后对跑出的最小割进行处理得出最小割的最小条数。

代码

#include<stdio.h>
#include<queue>
#include<iostream>
#define INF 0x3f3f3f3f
#define N 1005
using namespace std;
int list[N], listt[N], deep[N], tot;
struct Node
{
   int date, next, value;       
}cun[2000005];
struct b
{
   int x, t;       
}old, xin;
void add(int a, int b, int c)
{
   cun[++tot].date = b;
   cun[tot].value = c;
   cun[tot].next = list[a];
   list[a] = tot;     
   
   cun[++tot].date = a;
   cun[tot].value = 0;
   cun[tot].next = list[b];
   list[b] = tot;
}
int bfs(int s, int t, int n)
{
   queue<b> p;
   old.x = s;
   old.t = 0;
   p.push(old);
   memset(deep,255,sizeof(deep));
   deep[s] = 0;
   while(!p.empty())
   {
       old = p.front();
       p.pop();
       for(int i = list[old.x]; i; i = cun[i].next)
       {
          int date = cun[i].date;
          int value = cun[i].value;
          if(value == 0 || deep[date] != -1)  continue;
          xin.x = date;
          xin.t = old.t + 1;
          deep[date] = xin.t;
          p.push(xin);       
       }                 
   }   
   for(int i = 0; i <= n; i++)
   {
      listt[i] = list[i];        
   }
   return deep[t] != -1;
}
int minn(int a, int b)
{
   if(a < b)  return a;
   return b;    
}
int dfs(int s, int t, int min)
{
   if(s == t)  return min;
   int neww = 0;
   for(int i = listt[s]; i; i = cun[i].next)
   {
      listt[s] = i;
      int date = cun[i].date;
      int value = cun[i].value;
      if(value == 0 || deep[date] != deep[s] + 1)  continue;
      int m = dfs(date, t, minn(value, min - neww));
      neww += m;
      cun[i].value -= m;
      cun[i^1].value += m;
      if(neww == min)   break;        
   }    
   if(neww == 0)   deep[s] = 0;
   return neww;
}
int dinic(int s, int t, int n)
{
   int num = 0;
   while(bfs(s, t, n)) 
   {
      num += dfs(s, t, INF);             
   }   
   return num;
}
int main()
{
    int n, m, a, b, c, flag, T, flagg = 1;
    scanf("%d", &T);
    while(T--)
    {
      scanf("%d%d",&n,&m);
      memset(list,0,sizeof(list));
      tot = 1;
      for(int i = 1; i <= m; i++)
      {
         scanf("%d %d %d %d", &a, &b, &c, &flag); 
         add(a+1, b+1, c);
         if(flag)
          add(b+1, a+1, c);          
      }    
      int k = dinic(1, n, n+5);
      for(int i = 2; i <= tot; i += 2)
      {
         cun[i].value ++;       
      }
      k = dinic(1, n, n+5);
      printf("Case %d: %d\n", flagg++, k);                          
    }    
}

hdu 3987 求最小割条数最小

标签:io   os   sp   for   on   bs   代码   ad   ef   

原文地址:http://blog.csdn.net/q651111937/article/details/41654057

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!