3469

/*
最大流之 ISAP篇,2400+ms
,写了一晚上,累死了,纯粹的自己的版本,先放出个邻接表的版本。少了current优化,tle很久
*/ // include file #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <cctype> #include <ctime> #include <iostream> #include <sstream> #include <fstream> #include <iomanip> #include <bitset> #include <algorithm> #include <string> #include <vector> #include <queue> #include <set> #include <list> #include <functional> using namespace std; // typedef typedef long long LL; typedef unsigned long long ULL; typedef __int64 Bint; // #define read freopen("in.txt","r",stdin) #define write freopen("out.txt","w",stdout) #define FORi(a,b,c) for(int i=(a);i<(b);i+=c) #define FORj(a,b,c) for(int j=(a);j<(b);j+=c) #define FORk(a,b,c) for(int k=(a);k<(b);k+=c) #define FORp(a,b,c) for(int p=(a);p<(b);p+=c) #define FORii(a,b,c) for(int ii=(a);ii<(b);ii+=c) #define FORjj(a,b,c) for(int jj=(a);jj<(b);jj+=c) #define FORkk(a,b,c) for(int kk=(a);kk<(b);kk+=c) #define FF(i,a) for(int i=0;i<(a);i++) #define FFD(i,a) for(int i=(a)-1;i>=0;i--) #define Z(a) (a<<1) #define Y(a) (a>>1) const double eps = 1e-6; const double INFf = 1e10; const int INFi = 1000000000; const double Pi = acos(-1.0); template<class T> inline T sqr(T a){return a*a;} template<class T> inline T TMAX(T x,T y) { if(x>y) return x; return y; } template<class T> inline T TMIN(T x,T y) { if(x<y) return x; return y; } template<class T> inline void SWAP(T &x,T &y) { T t = x; x = y; y = t; } template<class T> inline T MMAX(T x,T y,T z) { return TMAX(TMAX(x,y),z); } // code begin #define MAXN 20010 #define MAXM 510000 int N,M; int source,sink; struct node1 { int e; int next; int residual; }; node1 mem[MAXM]; int G[MAXN]; // 正邻接表,正边和反向边在内存上差一 node1 Rmem[MAXM]; int RG[MAXN]; // 反邻接表,这样我们就能快速的知道正边和反边的地理位置了 int dis[MAXN]; // 到汇点的距离 int stk[MAXM],top; // 其实就是个栈嘛 int father[MAXN]; // 记录每个顶点的父亲 int curpos[MAXN]; // 每个点需要开始的位置 int laynum[MAXN]; // 每层的顶点个数 int que[MAXN]; // BFS用 void Add_edge(int dx,int a,int b,int c) { // 居然有重边 //if(dx>15000) printf("%d\n",dx); mem[dx].e = b; mem[dx].next = G[a]; mem[dx].residual += c; G[a] = dx; //if(rdx>15000) printf("%d\n",rdx); Rmem[dx].e = a; Rmem[dx].next = RG[b]; Rmem[dx].residual += c; RG[b] = dx; } void BFS() // 从汇点出发 { int head(0),tail(0); memset(laynum,0,sizeof(laynum)); FORi(1,N+1,1) { dis[i] = N; laynum[ dis[i] ] ++; } // 从汇点开始 laynum[ dis[sink] ] --; dis[ sink ] = 0; laynum[ dis[sink] ] ++; que[++tail] = sink; int mdx; while(head!=tail) { int cur = que[++head]; mdx = RG[cur]; while(mdx!=-1) { int v = Rmem[mdx].e; if( dis[v]==N && Rmem[mdx].residual!=0 ) { que[++tail] = v; laynum[N] --; dis[v] = dis[cur]+1; laynum[ dis[v] ]++; } mdx = Rmem[mdx].next; } } //printf("BFS success\n"); } int Augment() { int minp = INFi; FORi(0,top,1) { if(mem[stk[i]].residual<minp) minp = mem[stk[i]].residual; } // 找到做小边后,然后修改路径了 FORi(0,top,1) { mem[stk[i]].residual -= minp; mem[(stk[i]&1)?(stk[i]-1):(stk[i]+1)].residual += minp; } return minp; } int Retreat(int &cur) { // 找出所有儿子的最小值 int tmp; int mind(N-1); int mdx = G[cur]; while(mdx!=-1) { if( mem[mdx].residual>0 && dis[ mem[mdx].e ]<mind) mind = dis[ mem[mdx].e ]; mdx = mem[mdx].next; } tmp = dis[cur]; // relabel laynum[ dis[cur] ]--; dis[cur] = 1+mind; laynum[ dis[cur] ]++; //backtrack if(cur!=source) { cur = father[cur]; top --; } return laynum[ tmp ]; } int MaxFlow_ISAP() { int flow(0); BFS(); // 距离求出来了 // current优化 FORi(1,N+1,1) { curpos[i] = G[i]; } top = 0; memset(father,-1,sizeof(father)); int st = source; while( dis[st]<N ) { // int ds=-1,dsmx,mdx; mdx = curpos[st]; while(mdx!=-1) { int v = mem[mdx].e; if( mem[mdx].residual>0 && dis[st]==dis[v]+1 ) { ds = v; dsmx = mdx; break; } mdx = mem[mdx].next; } if(ds!=-1) //如果找到了 { curpos[st] = dsmx; stk[top++] = dsmx; father[ds] = st; st = ds; if(st==sink) { flow += Augment(); st = source; top = 0; } } else //如果没有找到 { curpos[st] = G[st]; if( Retreat(st) == 0 ) break; } } return flow; } int main() { read; write; int a,b,c,dx; while(scanf("%d %d",&N,&M)!=-1) { source = N+1; sink = N+2; dx = 0; memset(RG,-1,sizeof(RG)); memset(G,-1,sizeof(G)); memset(mem,0,sizeof(mem)); memset(Rmem,0,sizeof(Rmem)); FORi(1,N+1,1) { scanf("%d %d",&a,&b); Add_edge(dx++,source,i,a); Add_edge(dx++,i,source,a); Add_edge(dx++,i,sink,b); Add_edge(dx++,sink,i,b); } FORi(0,M,1) { scanf("%d %d %d",&a,&b,&c); Add_edge(dx++,a,b,c); Add_edge(dx++,b,a,c); } N+=2; printf("%d\n",MaxFlow_ISAP()); } return 0; }

posted @ 2011-03-15 23:49  AC2012  阅读(397)  评论(0编辑  收藏  举报