hdu 3599(最短路+最大流)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3599

思路:首先spfa求一下最短路,然后对于满足最短路上的边(dist[v]==dist[u]+w)加入到新图中来,边容量为1,最后求出的最大流就是没有相交的边的最短路径条数。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<string>
  4 #include<algorithm>
  5 #include<vector>
  6 #include<queue>
  7 using namespace std;
  8 #define MAXN 4444
  9 #define inf 1<<30
 10 
 11 struct Node{
 12     int v,w;
 13     Node(int vv,int ww):v(vv),w(ww){};
 14 };
 15 
 16 int n;
 17 bool mark[MAXN];
 18 int dist[MAXN];
 19 vector<vector<Node> >G;
 20 void spfa()
 21 {
 22     memset(mark,false,sizeof(mark));
 23     fill(dist,dist+n+2,inf);
 24     dist[1]=0;
 25     queue<int>que;
 26     que.push(1);
 27     while(!que.empty()){
 28         int u=que.front();
 29         que.pop();
 30         mark[u]=false;
 31         for(int i=0;i<G[u].size();i++){
 32             int v=G[u][i].v;
 33             int w=G[u][i].w;
 34             if(dist[u]+w<dist[v]){
 35                 dist[v]=dist[u]+w;
 36                 if(!mark[v]){
 37                     mark[v]=true;
 38                     que.push(v);
 39                 }
 40             }
 41         }
 42     }
 43 }
 44 
 45 struct Edge{
 46     int v,cap,next;
 47 }edge[MAXN*MAXN];
 48 
 49 int NE,NV;
 50 int head[MAXN];
 51 
 52 void Insert(int u,int v,int cap)
 53 {
 54     edge[NE].v=v;
 55     edge[NE].cap=cap;
 56     edge[NE].next=head[u];
 57     head[u]=NE++;
 58 
 59     edge[NE].v=u;
 60     edge[NE].cap=0;
 61     edge[NE].next=head[v];
 62     head[v]=NE++;
 63 }
 64 
 65 void Build()
 66 {
 67     NE=0;
 68     NV=n;
 69     memset(head,-1,sizeof(head));
 70     for(int u=1;u<=n;u++){
 71         for(int i=0;i<G[u].size();i++){
 72             int v=G[u][i].v,w=G[u][i].w;
 73             if(dist[u]+w==dist[v]){
 74                 Insert(u,v,1);
 75             }
 76         }
 77     }
 78 }
 79 
 80 int level[MAXN],gap[MAXN];
 81 void bfs(int vt)
 82 {
 83     memset(level,-1,sizeof(level));
 84     memset(gap,0,sizeof(gap));
 85     queue<int>que;
 86     que.push(vt);
 87     level[vt]=0;
 88     gap[level[vt]]++;
 89     while(!que.empty()){
 90         int u=que.front();
 91         que.pop();
 92         for(int i=head[u];i!=-1;i=edge[i].next){
 93             int v=edge[i].v;
 94             if(level[v]!=-1)continue;
 95             level[v]=level[u]+1;
 96             gap[level[v]]++;
 97             que.push(v);
 98         }
 99     }
100 }
101 
102 int pre[MAXN],cur[MAXN];
103 int SAP(int vs,int vt)
104 {
105     bfs(vt);
106     memset(pre,-1,sizeof(pre));
107     memcpy(cur,head,sizeof(head));
108     int u=pre[vs]=vs,aug=inf,maxflow=0;
109     gap[0]=NV;
110     while(level[vs]<NV){
111         bool flag=false;
112         for(int &i=cur[u];i!=-1;i=edge[i].next){
113             int v=edge[i].v;
114             if(edge[i].cap>0&&level[u]==level[v]+1){
115                 flag=true;
116                 aug=min(aug,edge[i].cap);
117                 pre[v]=u;
118                 u=v;
119                 if(v==vt){
120                     maxflow+=aug;
121                     for(u=pre[v];v!=vs;v=u,u=pre[u]){
122                         edge[cur[u]].cap-=aug;
123                         edge[cur[u]^1].cap+=aug;
124                     }
125                     aug=inf;
126                 }
127                 break;
128             }
129         }
130         if(flag)continue;
131         int minlevel=NV;
132         for(int i=head[u];i!=-1;i=edge[i].next){
133             int v=edge[i].v;
134             if(edge[i].cap>0&&level[v]<minlevel){
135                 minlevel=level[v];
136                 cur[u]=i;
137             }
138         }
139         if(--gap[level[u]]==0)break;
140         level[u]=minlevel+1;
141         gap[level[u]]++;
142         u=pre[u];
143     }
144     return maxflow;
145 }
146 
147 
148 int main()
149 {
150     int _case,u,v,w;
151     scanf("%d",&_case);
152     while(_case--){
153         scanf("%d",&n);
154         G.clear();
155         G.resize(n+2);
156         while(true){
157             scanf("%d%d%d",&u,&v,&w);
158             if(u==0&&v==0&&w==0)break;
159             G[u].push_back(Node(v,w));
160             G[v].push_back(Node(u,w));
161         }
162         spfa();
163         if(dist[n]==inf||n==1){
164             puts("0");
165             continue;
166         }
167         Build();
168         printf("%d\n",SAP(1,n));
169     }
170     return 0;
171 }
View Code

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值