大致题意
给n个点m条边的无向带权图,(n<=10000,m<=20000),其中一人想要从1走到n,另一人想要阻止他走最短路,于是他可以阻断一些路径,阻断路径的代价等于边的长度。要求使第一个人从1走到n无法走最短路的最小代价。
思路
多校1的签到题,跑出最短路,题目的意思就是在最短路上做最小割。
代码
贴一下dinic的板子,以后用。
(最短路好像有个打标记的优化 忘了)
#include<bits/stdc++.h>
using namespace std;
#define maxn 10005
#define maxm 1000006
#define ll long long int
#define INF 0x3f3f3f3f
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
#define mem(a) memset(a,0,sizeof(a))
#define sqr(x) (x*x)
#define inf (ll)2e18+1
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}
int T,n,m,a[maxn],b[maxn],c[maxn];
struct pp{int v,w,nxt;}edd[maxn];
int head[maxn],tot;
void adde(int x,int y,int z){edd[++tot]={y,z,head[x]};head[x]=tot;}
ll dis[maxn];
priority_queue<pair<ll,int> >q1;
///------------------------------------------
int s,t;
struct node{int v,f;};
vector<node>ed;
vector<int>e[maxn];
int dep[maxn];
queue<int>q;
void add(int x,int y,int z)
{
ed.push_back({y,z});
ed.push_back({x,0});
int k=ed.size();
e[x].push_back(k-2);
e[y].push_back(k-1);
}
bool bfs()
{
memset(dep,-1,sizeof(dep));
while(!q.empty())q.pop();
q.push(s);
dep[s]=1;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=0;i<e[u].size();i++){
int v=ed[e[u][i]].v;
int f=ed[e[u][i]].f;
if(dep[v]==-1&&f>0){
dep[v]=dep[u]+1;
q.push(v);
}
}
if(dep[t]>0)return true;
}
return false;
}
ll dfs(int x,ll f)
{
if(x==t)return f;
ll res=0;
for(int i=0;i<e[x].size();i++){
int v=ed[e[x][i]].v;
ll flow=(ll)ed[e[x][i]].f;
if(dep[v]==dep[x]+1&&flow){
ll dd=dfs(v,min(f,flow));
if(dd>0){
res+=dd;
f-=dd;
ed[e[x][i]].f-=dd;
ed[e[x][i]^1].f+=dd;
}
}
}
if(res==0)dep[x]=-1;
return res;
}
ll dinic()
{
ll res=0;
while(bfs()){
res+=dfs(s,inf);
}
return res;
}
///--------------------------------------------
void init()
{
while(!q1.empty())q1.pop();
ed.clear();
mem(head);
tot=0;
inc(i,1,n)e[i].clear();
}
int main()
{
T=read();
while(T--){
n=read();m=read();
int x,y,z;
init();
inc(i,1,n)dis[i]=inf;
inc(i,1,m){
x=read();y=read();z=read();
a[i]=x;b[i]=y;c[i]=z;
adde(x,y,z);
}
dis[1]=0;
q1.push(make_pair(0,1));
while(!q1.empty()){
int u=q1.top().second;q1.pop();
for(int i=head[u];i;i=edd[i].nxt){
int v=edd[i].v;
int w=edd[i].w;
if(dis[v]>dis[u]+1ll*w){
dis[v]=dis[u]+1ll*w;
q1.push(make_pair(-dis[v],v));
}
}
}
inc(i,1,m){
if(dis[a[i]]+1ll*c[i]==dis[b[i]])add(a[i],b[i],c[i]);
}
s=1;t=n;
ll ans=dinic();
printf("%lld\n",ans);
}
return 0;
}