http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2364
裸的最大流。。。
用了Dinic、ISAP、HLPP都TLE。。。
然后在网上看到了个贪心预流的优化,就AC了,2030ms
贪心预流仅用于预处理分层图网络流
HLPP一般适合处理分层图,但是怎么加了贪心预流还是T了。。DINIC和ISAP加了贪心预流就AC了。。
同时附上Dinic和贪心预流模板~
1 //#pragma comment(linker, "/STACK:102400000,102400000") 2 #include<cstdio> 3 #include<iostream> 4 #include<cstring> 5 #include<string> 6 #include<cmath> 7 #include<set> 8 #include<list> 9 #include<map> 10 #include<iterator> 11 #include<cstdlib> 12 #include<vector> 13 #include<queue> 14 #include<stack> 15 #include<algorithm> 16 #include<functional> 17 using namespace std; 18 typedef long long LL; 19 #define ROUND(x) round(x) 20 #define FLOOR(x) floor(x) 21 #define CEIL(x) ceil(x) 22 //const int maxn=0; 23 //const int inf=0x3f3f3f3f; 24 const LL inf64=0x3f3f3f3f3f3f3f3fLL; 25 const double INF=1e30; 26 const double eps=1e-6; 27 /** 28 *最大流最小割:加各种优化的Dinic算法($O(V^2E)$) 29 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇) 30 *输出:Dinic(NdFlow)(最大流),MinCut()(最小割)(需先求最大流) 31 *打印路径方法:按反向边(i&1)的flow 找,或者按边的flow找 32 */ 33 const int maxn=1510; 34 const int maxm=600010; 35 const int inf=0x3f3f3f3f; 36 struct Edge 37 { 38 int u,v; 39 int cap,flow; 40 int next; 41 } edge[maxm]; 42 int head[maxn],edgeNum;//需初始化 43 int n,m,d[maxn],cur[maxn]; 44 int st,ed; 45 bool vis[maxn]; 46 void addSubEdge(int u,int v,int cap,int flow) 47 { 48 edge[edgeNum].u=u; 49 edge[edgeNum].v=v; 50 edge[edgeNum].cap=cap; 51 edge[edgeNum].flow=flow; 52 edge[edgeNum].next=head[u]; 53 head[u]=edgeNum++; 54 cur[u]=head[u]; 55 } 56 void addEdge(int u,int v,int cap) 57 { 58 addSubEdge(u,v,cap,0); 59 addSubEdge(v,u,0,0);//注意加反向0 边 60 } 61 bool BFS() 62 { 63 queue<int> Q; 64 memset(vis, 0, sizeof(vis)); 65 Q.push(st); 66 d[st]=0; 67 vis[st]=1; 68 while (!Q.empty()) 69 { 70 int u=Q.front(); 71 Q.pop(); 72 for(int i=head[u]; i!=-1; i=edge[i].next) 73 { 74 int v=edge[i].v; 75 int w=edge[i].cap-edge[i].flow; 76 if(w>0 && !vis[v]) 77 { 78 vis[v]=1; 79 Q.push(v); 80 d[v]=d[u]+1; 81 if(v==ed) return 1; 82 } 83 } 84 } 85 return false; 86 } 87 int Aug(int u, int a) 88 { 89 if (u==ed) return a; 90 int aug=0, delta; 91 for(int &i=cur[u]; i!=-1; i=edge[i].next) 92 { 93 int v=edge[i].v; 94 int w=edge[i].cap-edge[i].flow; 95 if (w>0 && d[v]==d[u]+1) 96 { 97 delta = Aug(v, min(a,w)); 98 if (delta) 99 { 100 edge[i].flow += delta; 101 edge[i^1].flow -= delta; 102 aug += delta; 103 if (!(a-=delta)) break; 104 } 105 } 106 } 107 if (!aug) d[u]=-1; 108 return aug; 109 } 110 int Dinic(int NdFlow) 111 { 112 int flow=0; 113 while (BFS()) 114 { 115 memcpy(cur,head,sizeof(int)*(n+1)); 116 flow += Aug(st,inf); 117 /*如果超过指定流量就return 掉*/ 118 if(NdFlow==inf) continue; 119 if(flow > NdFlow) break; 120 } 121 return flow; 122 } 123 /*残余网络*/ 124 void Reduce() 125 { 126 for(int i=0; i<edgeNum; i++) edge[i].cap-=edge[i].flow; 127 } 128 /*清空流量*/ 129 void ClearFlow() 130 { 131 for(int i=0; i<edgeNum; i++) edge[i].flow=0; 132 } 133 /*求最小割*/ 134 vector<int> MinCut() 135 { 136 BFS(); 137 vector<int> ans; 138 for(int u=0; u<n; u++) 139 { 140 if(!vis[u]) continue; 141 for(int i=head[u]; i!=-1; i=edge[i].next) 142 { 143 if(i&1) continue;/*忽略反向边*/ 144 int v=edge[i].v; 145 int w=edge[i].cap; 146 if(!vis[v]&&w>0) ans.push_back(i); 147 } 148 } 149 return ans; 150 } 151 152 /** 153 *贪心预流:用于分层图Dinic预处理(从0到n-1) 154 *输入:图(链式前向星),n(顶点个数,包含源汇),st(源),ed(汇),rk[i]=i,level[](分层图的层次) 155 *输出:GreedyPreFlow()(预处理Dinic) 156 */ 157 int in[maxn],out[maxn]; 158 int level[maxn],rk[maxn]; 159 bool cmp(const int &i,const int &j) 160 { 161 return level[i]<level[j]; 162 } 163 void GreedyPreFlow() 164 { 165 memset(in, 0, sizeof (in)); 166 memset(out, 0, sizeof (out)); 167 sort(rk, rk+n, cmp); 168 in[st] = inf; 169 for (int i = 0; i < n; ++i) 170 { 171 int u = rk[i]; 172 for (int j = head[u]; j!=-1; j = edge[j].next) 173 { 174 int v = edge[j].v, w = edge[j].cap-edge[j].flow; 175 if (!(j & 1) && in[u] > out[u]) 176 { 177 int f = min(w, in[u]-out[u]); 178 in[v] += f, out[u] += f; 179 } 180 } 181 } 182 memset(in, 0, sizeof (in)); 183 in[ed] = inf; 184 for (int i = n-1; i >= 0; --i) 185 { 186 int v = rk[i]; 187 for (int j = head[v]; j!=-1; j = edge[j].next) 188 { 189 int u = edge[j].v, w = edge[j^1].cap-edge[j^1].flow; 190 if (j & 1 && out[u] > in[u]) 191 { 192 int f = min(w, min(out[u]-in[u], in[v])); 193 in[u] += f, in[v] -= f; 194 edge[j].flow -= f, edge[j^1].flow += f; 195 } 196 } 197 } 198 } 199 200 int N,M,L; 201 void init() 202 { 203 memset(head,-1,sizeof(head)); 204 edgeNum=0; 205 } 206 void input() 207 { 208 scanf("%d%d%d",&N,&M,&L); 209 int x=0; 210 int idx=0; 211 st=0,ed=0; 212 for(int i=0; i<N; i++) 213 { 214 scanf("%d",&x); 215 rk[i]=i; 216 level[i]=x; 217 if(x==1) st=i; 218 if(x==L) ed=i; 219 } 220 for(int i=0; i<M; i++) 221 { 222 int u,v,w; 223 scanf("%d%d%d",&u,&v,&w); 224 u--,v--; 225 addEdge(u,v,w); 226 } 227 n=N; 228 } 229 void solve() 230 { 231 GreedyPreFlow(); 232 ISAP(inf); 233 // cout<<HLPP()<<endl; 234 // cout<<Dinic(inf)<<endl; 235 for(int i=0; i<edgeNum; i+=2) printf("%d ",edge[i].flow); 236 } 237 void output() 238 { 239 // 240 } 241 int main() 242 { 243 // std::ios_base::sync_with_stdio(false); 244 // freopen("in.cpp","r",stdin); 245 int T; 246 scanf("%d",&T); 247 while(T--) 248 { 249 init(); 250 input(); 251 solve(); 252 output(); 253 } 254 return 0; 255 }