Path(双向SPFA+最小割,最短路会爆 int )

参考: https://blog.csdn.net/chenshibo17/article/details/97156743

Path

https://cn.vjudge.net/problem/HDU-6582

思路

1. 先算最短路,要是没有最短路就直接输出0(用SPFA找最短路)
2. 要是有的话新建一个图存所有的最短路(分别存从1到所有的和n到所有点的最短路,然后枚举每条边判断这条边
    是不是在最短路上,注意会爆int )
3. 在新建的图上跑一遍最小割(最大流等于最小割)

AC code
/*
Path
HDU - 6582
https://cn.vjudge.net/problem/HDU-6582
题意:割断所有的最短路所需要的代价
输入:
      T组样例
      点 边
      u->v w
样例输入:
      1
      3 4
      1 2 1
      2 3 1
      1 3 2
      1 3 3
样例输出:
      3
解法:
双向SPFA枚举每条边找出最短路的连通图
最小割来计算代价
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f
#define maxn 100100
#define ll long long
struct node{
  int u, v, w;
  int next;
}edge[maxn], uedge[maxn], wedge[maxn];
int head[maxn], uhead[maxn], whead[maxn];
int cnt, ucnt, wcnt;
ll dis[maxn], udis[maxn];
int d[maxn];
int t,n;
void init(){
  memset(head, -1, sizeof head);
  memset(uhead, -1, sizeof uhead);
  memset(whead, -1, sizeof whead);
  memset(dis, INF, sizeof dis);
  memset(udis, INF, sizeof udis);
  cnt = ucnt = wcnt = 0;
}
void add(int u, int v, int w, node edge[], int  &cnt, int *head){
  edge[cnt].w=w;
  edge[cnt].u=u;
  edge[cnt].v=v;
  edge[cnt].next=head[u];
  head[u]=cnt++;
}
void add_dinic(int u,int v,int w){
  wedge[wcnt].w=w;
  wedge[wcnt].u=u;
  wedge[wcnt].v=v;
  wedge[wcnt].next=whead[u];
  whead[u]=wcnt++;

  wedge[wcnt].w=0;
  wedge[wcnt].u=v;
  wedge[wcnt].v=u;
  wedge[wcnt].next=whead[v];
  whead[v]=wcnt++;
}
void spfa(int st, ll *dis, int *head, node edge[]){
  dis[st]=0;
  queue<int> q;
  q.push(st);
  while(!q.empty()){
    int u=q.front();
    q.pop();
    for(int i = head[u]; ~i; i = edge[i].next ){
      int v=edge[i].v;
      if(dis[v] > dis[u] + (ll)edge[i].w){
        dis[v] = dis[u] + (ll)edge[i].w;
        q.push(v);
      }
    }
  }
  return ;
}
bool bfs(){
  memset(d,-1,sizeof d);
  queue<int> q;
  d[1]=0;
  q.push(1);
  while(!q.empty()){
    int st=q.front();
    q.pop();
    for(int i=whead[st];~i;i=wedge[i].next){
      if(d[wedge[i].v]==-1&&wedge[i].w>0){
        d[wedge[i].v]=d[st]+1;
        q.push(wedge[i].v);
      }
    }
  }
  return d[n]!=-1;
}
int dfs(int a,int b){
  int r=0;
  if(a==n) return b;
  for(int i=whead[a];~i;i=wedge[i].next){
    if(wedge[i].w>0&&d[wedge[i].v]==d[a]+1){
      int x=min(wedge[i].w,b-r);
      x=dfs(wedge[i].v,x);
      r+=x;
      wedge[i].w-=x;
      wedge[i^1].w+=x;
    }
  }
  if(!r) d[a]=-2;
  return r;
}
ll dinic(){
  ll ans=0;
  int t;
  while(bfs()){
    while(t=dfs(1,INF)) ans+=(ll)t;
  }
  return ans;
}
int main(){
  int T;
  scanf("%d", &T);
  while(T--){
    scanf("%d %d", &n, &t);
    init();
    for(int i=0;i<t;i++){
      int u,v,w;
      scanf("%d %d %d", &u, &v, &w);
      add(u, v, w, edge, cnt, head);
      add(v, u, w, uedge, ucnt, uhead);
    }
    spfa(1, dis, head, edge);
    if(dis[n]==INF){
      printf("0\n");
      continue;
    }
    long long tmp = dis[n];
    spfa(n, udis, uhead, uedge);
    for(int i=0;i<t;i++){
      int u=edge[i].u,v=edge[i].v;
      if(dis[u]+udis[v]+edge[i].w==tmp){
        add_dinic(u,v,edge[i].w);
      }
    }
    printf("%lld\n", dinic());
  }
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值