hdu3870 基于最短路的最小割

题意:
     给你一个平面图,让你输出(1,1),(n ,n)的最小割..


思路:
      看完题想都没想直接最大流,结果TLE,想想也是 G<400*400,400*400*4>,这样的图超时不冤枉,后来在网上看了题解,都说是什么论文题目,果断去看论文结果没看懂,后来看了下别人的理解,自己再画画图大概知道是什么意思了,果断是看着没有证明的证明容易懂啊..


 把最小割转换成最短路是有限制条件的,就是这个图首先必须是平面图,然后要求的这两个点还必须是平面图最外侧的点,给你图解就明白了,感觉文字的东西越说越蒙..




看看上面的图就明白了吧,首先我们的目的就是要把s和t断开,也就是找一条横向的最短路径把他们切断,又因为路径的长度是根据容量来建的,所以最短路就是最小割..好想法...

#include<stdio.h>
#include<string.h>
#include<queue>

#define N_node 165000
#define N_edge 700000
#define INF 1000000000

using namespace std;

typedef struct
{
   int to ,cost ,next;
}STAR;

STAR E[N_edge];
int list[N_node] ,tot;
int s_x[N_node];
int map[405][405];

void add(int a, int b ,int c)
{
   E[++tot].to = b;
   E[tot].cost = c;
   E[tot].next = list[a];
   list[a] = tot;
   
   E[++tot].to = a;
   E[tot].cost = c;
   E[tot].next = list[b];
   list[b] = tot;
}

void SPFA(int s ,int n)
{
   for(int i = 0 ;i <= n ;i ++)
   s_x[i] = INF;
   int mark[N_node] = {0};
   mark[s] = 1;
   s_x[s] = 0;
   queue<int>q;
   q.push(s);
   while(!q.empty())
   {
      int tou ,xin;
      tou = q.front();
      q.pop();
      mark[tou] = 0;
      for(int k = list[tou] ;k ;k = E[k].next)
      {
         xin = E[k].to;
         if(s_x[xin] > s_x[tou] + E[k].cost)
         {
            s_x[xin] = s_x[tou] + E[k].cost;
            if(!mark[xin])
            {
               mark[xin] = 1;
               q.push(xin);
            }
         }
      }
   }
   return ;
}

int main ()
{
   int n ,i ,j ,t;
   scanf("%d" ,&t);
   while(t--)
   {
      scanf("%d" ,&n);
      for(i = 1 ;i <= n ;i ++)
      for(j = 1 ;j <= n ;j ++)
      scanf("%d" ,&map[i][j]);
      n--;
      int ss = 0 ,tt = n * n + 1;
      memset(list ,0 ,sizeof(list));
      tot = 1;
      for(i = 1 ;i <= n ;i ++)
      for(j = 1 ;j <= n ;j ++)
      {
         int now = (i - 1) * n + j;
         int to1 = (i - 1) * n + j + 1;
         int to2 = (i - 1) * n + j + n; 
         if(j != n) add(now ,to1 ,map[i][j+1]);
         if(i != n) add(now ,to2 ,map[i+1][j]);
         if(j == 1) add(ss ,now ,map[i][j]);
         if(i == n) add(ss ,now ,map[i+1][j]);
         if(j == n) add(now ,tt ,map[i][j+1]);
         if(i == 1) add(now ,tt ,map[i][j]);
      }
      SPFA(ss ,tt);
      printf("%d
" ,s_x[tt]);
   }
   return 0;
}

原文地址:https://www.cnblogs.com/csnd/p/12063150.html