HDU3416:最短路Dijkstra+网络流-

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

目录

题意:传送门

 原题目描述在最下面。
 给定一个n个节点,m条带权单向边的图,问从st到ed的最短路径有多少条。(路径不能重复

思路:

可行解:

 要建一个正向图和反向图,分别跑出从起点 st s t 和终点 ed e d 到各个点的最短路径。
 然后枚举每条边,判断这条边是不是最短路路径上的边,如果是就在给两个端点连一条容量为 1 1 流量为1的边。然后从 st s t ed e d 跑一遍最大流就可以了。

 好吧,这方法比较麻烦。。。可以只跑一次最短路。
某种解:

 只预处理处以终点 ed e d 为起点的最短路 dis[] d i s [ ] 。然后从起点开始 dfs d f s 搜索判断每条边是不是此最短路上的边。如果是,就把两端点连一条流量为 1 1 <script type="math/tex" id="MathJax-Element-170">1</script>的边。然后跑最大流

我ta丫疯狂wa,就是过不了,不知道为什么。但是有人可以过,我去。。。难受的一批

AC代码:
#include<bits/stdc++.h>
#define fuck(x) cout<<"* "<<x<<"\n"
using namespace std;
typedef long long LL;
const int N = 1e4+5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
struct lh{
  int u,w;
  lh(){}
  lh(int a,int b){u=a,w=b;}
  bool operator <(const lh &a)const{
    return w>a.w;
  }
};
struct node{
  int v,w,nex;
  node(){}
  node(int b,int c,int d){v=b,w=c,nex=d;}
}edge[N*20],rev[N*20];
struct lp{
  int to,w,nex;
  lp(){}
  lp(int a,int b,int c){to=a;w=b;nex=c;}
}cw[N*40];
int n,m,tot,dis[N],now[N],head[N],vis[N],revhead[N],revtot;
int st,ed,cnt,first[N],level[N];
void dij(){//以终点为起点跑dij
  memset(vis,0,sizeof(vis));
  dis[ed]=0;
  priority_queue<lh>Q;
  Q.push(lh(ed,0));
  while(!Q.empty()){
    lh b = Q.top();Q.pop();
    int u = b.u;
    if(vis[u])continue;
    vis[u]=1;
    for(int i=revhead[u];~i;i=rev[i].nex){
      int v = rev[i].v,w=rev[i].w;
      if(dis[v]>dis[u]+w){
        dis[v]=dis[u]+w;
        Q.push(lh(v,dis[v]));
      }
    }
  }
}
void dij2(){//以起点最起点跑dij
  memset(vis,0,sizeof(vis));
  now[st]=0;
  priority_queue<lh>Q;
  Q.push(lh(st,0));
  while(!Q.empty()){
    lh b = Q.top();Q.pop();
    int u = b.u;
    if(vis[u])continue;
    vis[u]=1;
    for(int i=head[u];~i;i=edge[i].nex){
      int v = edge[i].v,w=edge[i].w;
      if(now[v]>now[u]+w){
        now[v]=now[u]+w;
        Q.push(lh(v,now[v]));
      }
    }
  }
}
inline void add_dij(int u,int v,int c){//建立正向图和反向图
  edge[++tot]=node(v,c,head[u]);
  head[u]=tot;
  rev[++revtot]=node(u,c,revhead[v]);
  revhead[v]=revtot;
}
inline void add_edge(int u,int v,int c){//最大流建图
  cw[++cnt]=lp(v,c,first[u]);
  first[u]=cnt;
  cw[++cnt]=lp(u,0,first[v]);
  first[v]=cnt;
}
inline bool bfs(){
  memset(level,-1,sizeof(level));
  level[ed]=0;
  queue<int>Q;
  Q.push(ed);
  while(!Q.empty()){
    int u = Q.front();Q.pop();
    for(int i=first[u];~i;i=cw[i].nex){
      int v = cw[i].to;
      if(level[v]==-1&&cw[i^1].w){
        level[v]=level[u]+1;
        Q.push(v);
      }
    }
  }
  return level[st]!=-1;
}
int dinic(int u,int flow){
  if(u==ed||flow==0)return flow;
  int use=0,w;
  for(int i=first[u];~i;i=cw[i].nex){
    int v = cw[i].to;
    if(level[v]+1==level[u]&&cw[i].w){
      w = dinic(v,min(flow-use,cw[i].w));
      cw[i].w-=w;cw[i^1].w+=w;
      use+=w;
      if(use==flow)return flow;
    }
  }
  return use;
}
inline void init(){//初始化
  memset(head,-1,sizeof(head));
  memset(revhead,-1,sizeof(revhead));
  memset(first,-1,sizeof(first));
  cnt=tot=revtot=-1;
}
int main(){
  int tim;
  scanf("%d",&tim);
  while(tim--){
    scanf("%d%d",&n,&m);
    init();
    for(int i=0,u,v,c;i<m;++i){
      scanf("%d%d%d",&u,&v,&c);
      add_dij(u,v,c);
    }
    scanf("%d%d",&st,&ed);
    memset(dis,0x3f,sizeof(dis));
    memset(now,0x3f,sizeof(now));
    dij();dij2();
    //printf("**%d\n",now[ed]);
    //printf("dis[st] = %d\n", dis[st]);
    for(int i=1;i<=n;++i){
      for(int j=head[i];~j;j=edge[j].nex){
        int v = edge[j].v;
        if(now[i]+dis[v]+edge[j].w==dis[st]){
          add_edge(i,v,1);
          //printf("%d %d\n", i,v);
        }
      }
    }
    int ans=0;
    while(bfs())ans+=dinic(st,INF);
    printf("%d\n", ans);
  }
  return 0;
}


原题目描述:

Problem Description
Do not sincere non-interference。
Like that show, now starvae also take part in a show, but it take place between city A and B. Starvae is in city A and girls are in city B. Every time starvae can get to city B and make a data with a girl he likes. But there are two problems with it, one is starvae must get to B within least time, it’s said that he must take a shortest path. Other is no road can be taken more than once. While the city starvae passed away can been taken more than once.

So, under a good RP, starvae may have many chances to get to city B. But he don’t know how many chances at most he can make a data with the girl he likes . Could you help starvae?

Input
The first line is an integer T indicating the case number.(1<=T<=65)
For each case,there are two integer n and m in the first line ( 2<=n<=1000, 0<=m<=100000 ) ,n is the number of the city and m is the number of the roads.

Then follows m line ,each line have three integers a,b,c,(1<=a,b<=n,0 < c < = 1000)it means there is a road from a to b and it’s distance is c, while there may have no road from b to a. There may have a road from a to a,but you can ignore it. If there are two roads from a to b, they are different.

At last is a line with two integer A and B(1<=A,B<=N,A!=B), means the number of city A and city B.
There may be some blank line between each case.

Output
Output a line with a integer, means the chances starvae can get at most.

Sample Input

3
7 8
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
5 7 1
6 7 1
1 7

6 7
1 2 1
2 3 1
1 3 3
3 4 1
3 5 1
4 6 1
5 6 1
1 6

2 2
1 2 1
1 2 2
1 2

Sample Output

2
1
1

Author
starvae@HDU

Source
HDOJ Monthly Contest – 2010.06.05

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值