给你一个平面图,让你输出(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\n" ,s_x[tt]); } return 0; }