HDU 5889 Barricade

时间:2023-03-08 22:32:09
HDU 5889 Barricade

最短路,最小割,网络流。

可以根据$dis[u]+1$与$dis[v]$的大小关系判断$<u,v>$是否为最短路上的边,可以处理出一个只包含最短路的$DAG$,然后求这个$DAG$的最小割就可以了。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-;
void File()
{
freopen("D:\\in.txt","r",stdin);
freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
char c=getchar(); x=;
while(!isdigit(c)) c=getchar();
while(isdigit(c)) {x=x*+c-''; c=getchar();}
} const int maxn = + ;
const int INF = 0x7FFFFFFF;
struct Edge
{
int from, to, cap, flow;
Edge(int u, int v, int c, int f) :from(u), to(v), cap(c), flow(f){}
};
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
int n, m, s, t; void init()
{
for (int i = ; i < maxn; i++)
G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int cap)
{
edges.push_back(Edge(from, to, cap, ));
edges.push_back(Edge(to, from, , ));
int w = edges.size();
G[from].push_back(w - );
G[to].push_back(w - );
}
bool BFS()
{
memset(vis, , sizeof(vis));
queue<int>Q;
Q.push(s);
d[s] = ;
vis[s] = ;
while (!Q.empty())
{
int x = Q.front();
Q.pop();
for (int i = ; i<G[x].size(); i++)
{
Edge e = edges[G[x][i]];
if (!vis[e.to] && e.cap>e.flow)
{
vis[e.to] = ;
d[e.to] = d[x] + ;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a)
{
if (x == t || a == )
return a;
int flow = , f;
for (int &i = cur[x]; i<G[x].size(); i++)
{
Edge e = edges[G[x][i]];
if (d[x]+ == d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>)
{
edges[G[x][i]].flow+=f;
edges[G[x][i] ^ ].flow-=f;
flow+=f;
a-=f;
if(a==) break;
}
}
if(!flow) d[x] = -;
return flow;
}
int dinic(int s, int t)
{
int flow = ;
while (BFS())
{
memset(cur, , sizeof(cur));
flow += DFS(s, INF);
}
return flow;
} int h[maxn],sz,T;
struct X
{
int u,v,w,nx;
}ee[maxn];
int dis[maxn],flag[maxn]; void add(int a,int b,int c)
{
ee[sz].u=a; ee[sz].v=b; ee[sz].w=c;
ee[sz].nx=h[a]; h[a]=sz++;
} void spfa()
{
for(int i=;i<=n;i++) dis[i]=INF ,flag[i]=;
dis[]=; queue<int>Q; Q.push(); flag[]=; while(!Q.empty())
{
int top=Q.front(); Q.pop(); flag[top]=;
for(int i=h[top];i!=-;i=ee[i].nx)
{
if(dis[top]+<dis[ee[i].v])
{
dis[ee[i].v]=dis[top]+;
if(flag[ee[i].v]==)
{
flag[ee[i].v]=;
Q.push(ee[i].v);
}
}
}
}
} int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m); sz=;
memset(h,-,sizeof h);
for(int i=;i<=m;i++)
{
int u,v,w; scanf("%d%d%d",&u,&v,&w);
add(u,v,w); add(v,u,w);
}
spfa(); init();
for(int i=;i<sz;i++)
{
if(dis[ee[i].u]+==dis[ee[i].v])
{
AddEdge(ee[i].u,ee[i].v,ee[i].w);
}
}
s=; t=n;
printf("%d\n",dinic(s,t));
}
return ;
}