Path
Path
题解
一道很明显的网络流。
由于题目只想让最小路径变大一点,所以我们可以把所有最短路径建成一张网络,然后,我们就可以找出这个图的最小割。
很显然,最小割的值就是我们总共封路的花费。
注意要开long long,笔者因为这个WA了好久。
如果打的dijk要加堆优化,否则会TLE。
源码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
#define MAXN 200005
using namespace std;
typedef long long LL;
#define gc() getchar()
const LL INF=0x7f7f7f7f7f7f;
int tot,head[MAXN],n,m;
int from[MAXN<<1],to[MAXN<<1];
int nxt[MAXN<<1],s,t;
LL paid[MAXN<<1];
struct ming{
int v;LL w;
ming(){
v=w=0;
}
ming(int V,LL W){
v=V;w=W;
}
};
vector<ming> G[MAXN],B[MAXN];
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=gc();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=gc();}
while(s>='0'&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=gc();}
x*=f;
}
void addEdge(int u,int v,int w){
from[++tot]=u;to[tot]=v;paid[tot]=w;
nxt[tot]=head[u];head[u]=tot;
}
void addedge(int u,int v,int w){
addEdge(u,v,w);
addEdge(v,u,0);
}
queue<int> q;
int d[MAXN];
bool bfs(){
memset(d,0,sizeof(d));
while(!q.empty()) q.pop();
q.push(s);d[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
if(u==t) return true;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(!d[v]&&paid[i]>0)
d[v]=d[u]+1,q.push(v);
}
}
return false;
}
LL dfs(int u,LL flow){
if(u==t||!flow) return flow;
LL tmp=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i];
if(d[v]==d[u]+1&&paid[i]>0){
LL now_flow=dfs(v,min(flow,paid[i]));
paid[i]-=now_flow;paid[i^1]+=now_flow;
flow-=now_flow;tmp+=now_flow;
if(flow+tmp==now_flow){
return flow+tmp;
}
if(!flow) break;
}
}
if(!tmp) d[u]=0;
return tmp;
}
LL dinic(){
LL res=0;
while(bfs())
res+=dfs(s,INF);
return res;
}
LL dis[MAXN];
bool vis[MAXN];
queue<int> q1;
typedef pair<LL,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >qq;
void dijk(){
for(int i=1;i<=n;i++) dis[i]=INF,vis[i]=0;
while(!qq.empty()) qq.pop();
dis[1]=0;qq.push(make_pair(0,s));
while(!qq.empty()){
int k=qq.top().second;qq.pop();
if(vis[k]) continue;
vis[k]=true;int siz=G[k].size();
for(int j=0;j<siz;j++){
if(dis[G[k][j].v]>dis[k]+G[k][j].w){
dis[G[k][j].v]=dis[k]+G[k][j].w;
qq.push(make_pair(dis[G[k][j].v],G[k][j].v));
}
}
}
}
bool inque[MAXN];
void init(){
for(int i=1;i<=n;i++) inque[i]=false;
while(!q1.empty()) q1.pop();
q1.push(n);inque[n]=true;
while(!q1.empty()){
int u=q1.front();q1.pop();
int siz=B[u].size();
for(int i=0;i<siz;i++){
if(dis[B[u][i].v]+B[u][i].w==dis[u]){
addedge(B[u][i].v,u,B[u][i].w);
if(inque[B[u][i].v]) continue;
q1.push(B[u][i].v);inque[B[u][i].v]=true;
}
}
}
}
int main() {
int tt;read(tt);
while(tt--){
tot=-1;memset(head,-1,sizeof(head));
read(n);read(m);s=1;t=n;
for(int i=1;i<=m;i++){
int u,v;LL w;read(u);read(v);read(w);
G[u].push_back(ming(v,w));
B[v].push_back(ming(u,w));
}
dijk();
if(dis[n]<INF-1) init(),printf("%lld\n",dinic());
else puts("0");
for(int i=1;i<=n;i++)G[i].clear(),B[i].clear();
}
return 0;
}