题目链接:E - Path HDU - 6582
题意:给定n个点,m条有向边,首先求出最短路,然后在这张新图上跑最小割
最短路和最小割都是板子,我们现在关注的就是如何构造出这张图:
for(int u=1;u<=n;++u)
for(int i=head[u];i!=-1;i=edge[i].next)
if(dis[edge[i].v]==dis[u]+edge[i].w){
++id;
line[id].u=u;
line[id].v=v;
line[id].w=w;
}
ok。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e4+7;
const int maxm=2e4+7;
struct Edge{
int v,next;
ll w;
}edge[maxm],edge1[maxm];
int head[maxn],head1[maxn],top,top1;
void init(int n){
top=0;
for(int i=1;i<=n;++i) head[i]=-1;
}
void init1(int n){
top1=0;
for(int i=1;i<=n;++i) head1[i]=-1;
}
void add(int u,int v,ll w){
edge[top].v=v;
edge[top].w=w;
edge[top].next=head[u];
head[u]=top++;
}
void add1(int u,int v,ll w){
edge1[top1].v=v;
edge1[top1].w=w;
edge1[top1].next=head1[u];
head1[u]=top1++;
}
priority_queue<pair<ll,int> > yq;
const ll inf=0x3f3f3f3f3f3f3f3f;
ll dis[maxn];
bool vis[maxn];
void dij(int n){
while(!yq.empty()) yq.pop();
for(int i=1;i<=n;++i) vis[i]=0,dis[i]=inf;
int u,v;
ll w;
dis[1]=0;
yq.push({0,1});
while(!yq.empty()){
u=yq.top().second; yq.pop();
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next){
v=edge[i].v;
w=edge[i].w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
yq.push({-dis[v],v});
}
}
}
}
queue<int> q;
int s,t;
ll maxflow;
int d[maxn];
bool bfs(){
memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
q.push(s);
int v;
ll w;
d[s]=1;
while(!q.empty()){
int u=q.front(); q.pop();
for(int i=head1[u];i!=-1;i=edge1[i].next){
v=edge1[i].v;
w=edge1[i].w;
if(w&&!d[v]){
q.push(v);
d[v]=d[u]+1;
if(v==t) return 1;
}
}
}
return 0;
}
ll dinic(int u,ll flow){
if(u==t) return flow;
ll res=flow,k;
for(int i=head1[u];(i!=-1)&&res;i=edge1[i].next){
ll w=edge1[i].w;
int v=edge1[i].v;
if(w&&d[v]==d[u]+1){
k=dinic(v,min(res,w));
if(!k) d[v]=0;
edge1[i].w-=k;
edge1[i^1].w+=k;
res-=k;
}
}
return flow-res;
}
int main(){
int T,n,m;
int u,v,w;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
init(n);
while(m--){
scanf("%d%d%d",&u,&v,&w);
add(u,v,1LL*w);
}
dij(n);
if(dis[n]==inf) printf("0\n");
else{
init1(n);
int hh=0;
for(u=1;u<=n;++u)
for(int i=head[u];i!=-1;i=edge[i].next)
if(dis[edge[i].v]==dis[u]+edge[i].w){
//cout<<u<<" "<<edge[i].v<<" "<<edge[i].w<<endl;
add1(u,edge[i].v,edge[i].w),add1(edge[i].v,u,0);
}
ll flow;
s=1,t=n;
maxflow=0;
while(bfs()){
while(flow=dinic(1,inf)) maxflow+=flow;
}
printf("%lld\n",maxflow);
}
}
return 0;
}