给你一个平面图,要求从求出从左上角到右下角的最小割。
思路:
如果大意的可能直接上来一遍最大流,然后就会各种悲剧的MLE,TLE,其实这个题目可以用到有个论文里面的那个平面图最小割转最短路(hdu3870 也是这种问题),我们证明说着费劲直接给一个图片理解就行了,思路就是这张图片
这个题目用Spfa会超时的,要用优化过的Dij才能过,我不会的优化过的Dij,直接用模板过的。
#include<stdio.h> #include<string.h> #include<queue> using namespace std; //************************************************* #include<queue> #define FOR(i,a,b) for(int i=a;i<=b;++i) #define clr(f,z) memset(f,z,sizeof(f)) #define LL long long using namespace std; const int mm=1e6+9; const LL oo=1e16; class Edge { public:int v,next;LL w; }; class Dot { public:LL dis;int v; Dot(){} Dot(int _v,LL _d) { v=_v;dis=_d; } bool operator<(const Dot&x)const { return dis>x.dis; } }; class ShortPath { public: int head[mm],edge;Edge e[3000000]; void clear() { clr(head,-1);edge=0; } void add(int u,int v,LL w) { e[edge].v=v;e[edge].w=w;e[edge].next=head[u];head[u]=edge++; } bool vis[mm];int id[mm];LL dis[mm]; priority_queue<Dot>Q; LL dijstra(int s,int t,int n) { int u,v;Dot uu; FOR(i,0,n)dis[i]=oo,vis[i]=0; Q.push(Dot(s,0));dis[s]=0; while(!Q.empty()) { uu=Q.top();Q.pop();u=uu.v; if(vis[u])continue;vis[u]=1; for(int i=head[u];~i;i=e[i].next) { v=e[i].v; if(!vis[v]&&dis[v]>dis[u]+e[i].w) { dis[v]=dis[u]+e[i].w; Q.push(Dot(v,dis[v])); } } } return dis[t]; } }sf; //sf.clear(); //sf.add(); //sf.dijstra(s ,t ,n); //******************************** int main () { int n ,m ,i ,j ,a ,b ,now ,p1 ,p2 ,p3 ,p4; while(~scanf("%d %d" ,&n ,&m)) { int s = 0 ,t = n * m * 4 + 1; sf.clear(); for(i = 1 ;i <= n + 1;i ++) for(j = 1 ;j <= m ;j ++) { scanf("%d" ,&a); now = (i - 1) * m + j; p1 = (now - 1) * 4 + 1; p2 = (now - 1) * 4 + 2; p3 = (now - 1) * 4 + 3; p4 = (now - 1) * 4 + 4; if(i == 1) sf.add(s ,p2 ,a); else if(i == n + 1) { int p44 = ((i - 1 - 1) * m + j - 1) * 4 + 4; sf.add(p44 ,t ,a); } else { int noww = now - m; sf.add(p2 ,(noww - 1) * 4 + 4 ,a); sf.add((noww - 1) * 4 + 4 ,p2 ,a); } } for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= m + 1 ;j ++) { scanf("%d" ,&a); now = (i - 1) * m + j; p1 = (now - 1) * 4 + 1; p2 = (now - 1) * 4 + 2; p3 = (now - 1) * 4 + 3; p4 = (now - 1) * 4 + 4; if(j == 1) sf.add(p1 ,t ,a); else if(j == m + 1) { int p33 = ((i - 1) * m + j - 1 - 1) * 4 + 3; sf.add(s ,p33 ,a); } else { int noww = now - 1; sf.add(p1 ,(noww - 1) * 4 + 3 ,a); sf.add((noww - 1) * 4 + 3 ,p1 ,a); } } for(i = 1 ;i <= n * 2 ;i ++) for(j = 1 ;j <= m ;j ++) { scanf("%d %d" ,&a ,&b); int ii = (i + 1) / 2; now = (ii - 1) * m + j; p1 = (now - 1) * 4 + 1; p2 = (now - 1) * 4 + 2; p3 = (now - 1) * 4 + 3; p4 = (now - 1) * 4 + 4; if(i & 1) { sf.add(p1 ,p2 ,a) ,sf.add(p2 ,p1 ,a); sf.add(p2 ,p3 ,b) ,sf.add(p3 ,p2 ,b); } else { sf.add(p3 ,p4 ,b) ,sf.add(p4 ,p3 ,b); sf.add(p4 ,p1 ,a) ,sf.add(p1 ,p4 ,a); } } printf("%d " ,sf.dijstra(s ,t ,t)); } return 0; }