emmmm LOJ这个最大流加强版卡掉了我心爱的Dinic板子
加强版最大流
这这这也太丝滑了吧 LOJ板子题跑了400ms
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("avx")
#include <bits/stdc++.h>
using namespace std;
int getint() {
char c;
while (not isdigit(c = getchar()))
;
int res = c - '0';
while (isdigit(c = getchar())) res = res * 10 + (c - '0');
return res;
}
template <class T>
struct push_relabel {
struct arc {
int to, rev;
T cap;
};
const T inf = numeric_limits<T>::max();
const int n;
vector<tuple<int, int, T, T>> arc_pool;
vector<arc> g;
vector<int> head, ptr, d;
vector<T> ex;
vector<vector<int>> active;
vector<set<int>> vs;
int highest, works;
push_relabel(int _n) : n(_n), head(n + 1), ptr(n), d(n), ex(n), active(n), vs(n) {
}
void add(int from, int to, T cap, bool directed = true) {
assert(cap >= 0);
if (from == to or cap == 0)
return;
arc_pool.emplace_back(from, to, cap, directed ? 0 : cap);
++head[from], ++head[to];
}
void build() {
for (int v = 0; v < n; ++v) head[v + 1] += head[v];
g.resize(head[n]);
for (auto&& e : arc_pool) {
int i = --head[get<0>(e)], j = --head[get<1>(e)];
g[i] = {
get<1>(e), j, get<2>(e) }, g[j] = {
get<0>(e), i, get<3>(e) };
}
}
void push(int v, arc& a) {
if (ex[a.to] == 0)
active[d[a.to]].push_back(a.to);
T delta = min(ex[v], a.cap);
ex[v] -= delta, ex[a.to] += delta;
a.cap -= delta, g[a.rev].cap += delta;
}
void relabel(int v) {
++works;
int mn = 2 * n;
for (int i = head[v]; i < head[v + 1]; ++i)
if (g[i].cap)
mn = min(mn, d[g[i].to]);
if (vs[d[v]].size() == 1) {
for (int i = d[v]; i < n; ++i) {
for (int u : vs[i]) d[u] = n;
active[i].clear(), vs[i].clear();
}
return;
}
vs[d[v]].erase(v);
if ((d[v] = mn + 1) < n)
vs[highest = d[v]].insert(v);
}
void discharge(int v) {
int i = ptr[v];
while (ex[v]) {
if (i == head[v + 1]) {
relabel(v), i = head[v];
if (d[v] >= n)
break;
} else {
if (g[i].cap and d[v] > d[g[i].to])
push(v, g[i]);
else
++i;
}
}
ptr[v] = i;
}
void global_relabel(int t) {
copy(begin(head), begin(head) + n, begin(ptr));
fill(begin(d), end(d), n);
for (int i = 0; i < n; ++i) active[i].clear(), vs[i].clear();
highest = -1, works = 0;
queue<int> que;
d[t] = 0, que.push(t);
while (not que.empty()) {
int v = que.front();
que.pop();
vs[d[v]].insert(v);
for (int i = head[v]; i < head[v + 1]; ++i)
if (g[g[i].rev].cap and d[g[i].to] == n) {
d[g[i].to] = d[v] + 1, que.push(g[i].to);
if (ex[g[i].to])
active[highest = d[g[i].to]].push_back(g[i].to);
}
}
}
T max_flow(int s, int t) {
build();
ex[s] = inf, ex[t] = -inf;
for (int i = head[s]; i < head[s + 1]; ++i) push(s, g[i]);
global_relabel(t);
for (; highest >= 0; --highest)
while (not active[highest].empty()) {
int v = active[highest].back();
active[highest].pop_back();
discharge(v);
if (works > 4 * n)
global_relabel(t);
}
return inf + ex[t];
}
};
struct stopwatch {
clock_t t = clock();
void restart() {
t = clock(); }
int elapsed() const {
return (clock() - t) * 1000 / CLOCKS_PER_SEC; }
friend string to_string(stopwatch sw) {
return "Time: " + to_string(sw.elapsed()) + " ms"; }
} sw;
int main() {
int n = getint(), m = getint(), s = getint() - 1, t = getint() - 1;
push_relabel<int> g(n);
while (m--) {
int u = getint() - 1, v = getint() - 1, c = getint();
g.add(u, v, c);
}
cout << g.max_flow(s, t) << '\n';
}
再来看看这份 7K多ms
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
inline int Read(){
int x=0;
char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
return x;
}
const int inf=1<<30;
int top=1,head[10100];
int n,m,s,t;
int e[10100],h[10100],cnth[20100];//每个点对应的余流,高度;每个高度有多少个点
struct cmp{
inline bool operator () (int a,int b) const{
return h[a]<h[b];
}
};
struct Node{
int v;
int val;
int next;
}node[400100];
inline void addedge(int u,int v,int val){
node[++top].v=v;
node[top].val=val;
node[top].next=head[u];
head[u]=top;
}
inline void add(int u,int v,int val){
addedge(u,v,val);
addedge(v,u,0);
}
int inque[11000];
void bfs(){
memset(h,0x3f,sizeof(h));
h[t]=0;
queue<int>qu;
qu.push(t);
while(!qu.empty()){
int u=qu.front();
qu.pop();
inque[u]=0;
for(int i=head[u];i;i=node[i].next){
int d=node[i].v;
if(node[i^1].val&&h[d]>h[u]+1){
//反向跑
h[d]=h[u]+1;
if(inque[d]==0){
qu.push(d);
inque[d]=1;
}
}
}
}
return;
}
priority_queue<int,vector<int>,cmp>q;
inline void push_(int u){
for(int i=head[u];i;i=node[i].next){
int d=node[i].v;
if(node[i].val&&h[d]+1==h[u]){
//可以推流
int mi=min(node[i].val,e[u]);
node[i].val-=mi;
node[i^1].val+=mi;
e[u]-=mi;
e[d]+=mi;
if(inque[d]==0&&d!=t&&d!=s){
q.push(d);
inque[d]=1;
}
if(e[u]==0)break;//已经推完了
}
}
}//推流
inline void relabel(int u){
h[u]=inf;
for(int i=head[u];i;i=node[i].next){
int d=node[i].v;
if(node[i].val&&h[d]+1<h[u]){
h[u]=h[d]+1;
}
}
}//把u的高度更改为与u相邻的最低的点的高度加1
int hlpp(){
register int i;
bfs();
if(h[s]==0x3f3f3f3f)return 0;//s与t不连通
h[s]=n;
for(i=1;i<=n;i++)if(h[i]<0x3f3f3f3f)cnth[h[i]]++;//统计各个高度的点数,注意不要让下标越界
for(i=head[s];i;i=node[i].next){
int d=node[i].v;
int mi=node[i].val;
if(mi){
e[s]-=mi;
e[d]+=mi;
node[i].val-=mi;
node[i^1].val+=mi;
if(d!=t&&inque[d]==0&&d!=s){
q.push(d);
inque[d]=1;
}
}
}//从s向周围点推流
while(!q.empty()){
int u=q.top();
inque[u]=0;
q.pop();
push_(u);
if(e[u]){
//还有余流
cnth[h[u]]--;
if(cnth[h[u]]==0){
for(int i=1;i<=n;i++){
if(i!=s&&i!=t&&h[i]>h[u]&&h[i]<n+1){
h[i]=n+1;//标记无法到达
}
}
}//gap优化
relabel(u);
cnth[h[u]]++;
q.push(u);
inque[u]=1;
}
}
return e[t];
}
int main(){
n=Read(),m=Read(),s=Read(),t=Read();
register int i;
int u,v,val;
for(i=1;i<=m;i++)u=Read(),v=Read(),val=Read(),add(u,v,val);
printf("%d",hlpp());
return 0;
}
先来一个懵逼费用流 (无脑TLE)
费用流||KM都可以
第一发交了个暴力建图,TLE了,重新读题发现有重边,后来考虑过的都想进去了,还是无脑TLE = 。= 好像是数组开小了的锅 (HDU真莫名其妙 )
#include <bits/stdc++.h>
#include <stdlib.h>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include<queue>
#include <time.h>
#include <cstdio>
#include <iostream>
#include <vector>
#define ll int
//#define int long long
//#define inf 0x3f3f3f3f
#define mods 1000000007
#define modd 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x & (-x))
#define mp make_pair
#define pb push_back
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#define Re register int
using namespace std;
const int N=10000,M=1e6+3,inf=1e9;
int x,y,z,w,o=1,n,m,h,t,st,ed,cyf[N],pan[N],pre[N],dis[N],head[N];
ll mincost,maxflow;
ll hnr;
ll xfz;
struct QAQ{
int w,to,next,flow;}a[M<<1];
queue<int>Q;
inline void read(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
inline void add(Re x,Re y,Re z,Re w){
a[++o].flow=z,a[o].w=w,a[o].to=y,a[o].next=head[x],head[x]=o;}
inline void add_(Re a,Re b,Re flow,Re w){
add(a,b,flow,w),add(b,a,0,-w);}
inline int SPFA(Re st,Re ed){
for(Re i=0;i<=2*n+1;++i)dis[i]=inf,pan[i]=0; //有多少个点就初始化到那个地方去
Q.push(st),pan[st]=1,dis[st]=0,cyf[st]=inf;
while(!Q.empty()){
Re x=Q.front();Q.pop();pan[x]=0;
for(Re i=head[x],to;i;i=a[i].next)
if(a[i].flow&&dis[to=a[i].to]>dis[x]+a[i].w){
dis[to]=dis[x]+a[i].w,pre[to]=i;
cyf[to]=min(cyf[x],a[i].flow);
if(!pan[to])pan[to]=1,Q.push(to);
}
}
return dis[ed]!=inf;
}
inline void EK(Re st,Re ed){
while(SPFA(st,ed)){
Re x=ed;maxflow+=cyf[ed],mincost+=(ll)cyf[ed]*dis[ed];
while(x!=st){
//和最大流一样的更新
Re i=pre[x];
a[i].flow-=cyf[ed];
a[i^1].flow+=cyf[ed];
x=a[i^1].to;
}
}
}
ll e[300][300];
void cle(){
o=1;
maxflow=0;
mincost=0;
for(int i=0;i<=5000;i++){
head[i]=0;
}
}
signed main(){
ll t;
read(t);
while(t--){
read(n);
read(m);
cle();
for(int i=1;i<=n;i++){
add_(0,i,1,0);
add_(i+n,2*n+1,1,0);
for(int j=1;j<=n;j++){
e[i][j]=inf;
}
}
for(int i=1;i<=m;i++){
ll u,v,w;
read(u);
read(v);
read(w);
e[u][v]=min(e[u][v],w);
//add_(u,v+n,1,w);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
// if(j==i){continue;}
if(e[i][j]<inf){
add_(i,j+n,1,e[i][j]);
// add_(j+n,i,1,e[i][j]);
}
}
}
st=0;
ed=2*n+1;
EK(st,ed);
printf("%d\n",mincost);
}
return 0;
}