War(最短路+最大流)

War

http://acm.hdu.edu.cn/showproblem.php?pid=3599

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1870    Accepted Submission(s): 442


Problem Description
In the war between Anihc and Bandzi, Anihc has won Bangzi. At that time, Lvbin, the king of Anihc, want to start from Bangzi to beat Nebir across the channel between them. He let his army get to there as soon as possible, and there located many islands which can be used to have a break. In order to save time, the king forbid the army getting through the same pass for more than one time, but they can reach the same island for as many as times they want.
Yunfeng, the General of the army, must tell how many optimal ship routes are there to the king as soon as possible, or he will be killed. Now he asks for your help. You must help Yunfeng to save his life.
He tells you that there are N island. The islands are numbered from 1 to N(1 is Bangzi and N is Nebir, others are many islands). And there are many ways, each way contain the islands number U and V and the length W. Please output your answer.
 
Input
The first line in the input file contains a single integer number T means the case number. 
Each case contains a number N (N<=1500) means the number of the islands. 
And then many lines follow. Each line contains three numbers: U V W (W<10000), means that the distance between island U and V is W. The input of ways are terminated by “ 0 0 0 ”.
 
Output
Print the number of the optimal ship routes are there after each case in a line.
 
Sample Input
1
6
1 2 1
3 2 1
3 4 1
1 3 2
4 2 2
4 5 1
5 6 1
4 6 2
0 0 0
 
Sample Output
2
 
Author
alpc92
 
Source
 
 
 
  1 #include<iostream>
  2 #include<cstring>
  3 #include<string>
  4 #include<cmath>
  5 #include<cstdio>
  6 #include<algorithm>
  7 #include<queue>
  8 #include<vector>
  9 #include<set>
 10 #define INF 0x3f3f3f3f
 11 #define maxn 2005
 12 #define MAXN 1000005
 13 #define mem(a,b) memset(a,b,sizeof(a))
 14 using namespace std;
 15 
 16 int n;
 17 struct sair{
 18     int len,pos;
 19     bool operator<(const sair &b)const{
 20         return len>b.len;
 21     }
 22 };
 23 int dis[maxn];
 24 int vis[maxn];
 25 vector<pair<int,int> >ve[maxn];
 26 void Dijstra(){
 27     priority_queue<sair>q;
 28     sair tmp;
 29     tmp.len=0,tmp.pos=1;
 30     dis[1]=0;
 31     q.push(tmp);
 32     while(!q.empty()){
 33         tmp=q.top();
 34         q.pop();
 35         int pos=tmp.pos;
 36         if(vis[pos]){
 37             continue;
 38         }
 39         vis[pos]=1;
 40         for(int i=0;i<ve[pos].size();i++){
 41             int f=ve[pos][i].first;
 42             int len=ve[pos][i].second;
 43 
 44             if(dis[f]>dis[pos]+len){
 45                 dis[f]=dis[pos]+len;
 46                 tmp.pos=f;
 47                 tmp.len=dis[f];
 48                 q.push(tmp);
 49             }
 50         }
 51     }
 52 }
 53 
 54 struct Edge{
 55     int v,next;
 56     int cap,flow;
 57 }edge[MAXN*5];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
 58 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
 59 int cnt=0;//实际存储总边数
 60 void isap_init()
 61 {
 62     cnt=0;
 63     memset(pre,-1,sizeof(pre));
 64 }
 65 void isap_add(int u,int v,int w)//加边
 66 {
 67     edge[cnt].v=v;
 68     edge[cnt].cap=w;
 69     edge[cnt].flow=0;
 70     edge[cnt].next=pre[u];
 71     pre[u]=cnt++;
 72 }
 73 void add(int u,int v,int w){
 74     isap_add(u,v,w);
 75     isap_add(v,u,0);
 76 }
 77 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
 78 {
 79     memset(dep,-1,sizeof(dep));
 80     memset(gap,0,sizeof(gap));
 81     gap[0]=1;
 82     dep[t]=0;
 83     queue<int>q;
 84     while(!q.empty()) q.pop();
 85     q.push(t);//从汇点开始反向建层次图
 86     while(!q.empty())
 87     {
 88         int u=q.front();
 89         q.pop();
 90         for(int i=pre[u];i!=-1;i=edge[i].next)
 91         {
 92             int v=edge[i].v;
 93             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
 94             {
 95                 dep[v]=dep[u]+1;
 96                 gap[dep[v]]++;
 97                 q.push(v);
 98                 //if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
 99                 //break;
100             }
101         }
102     }
103     return dep[s]!=-1;
104 }
105 int isap(int s,int t)
106 {
107     if(!bfs(s,t))
108     return 0;
109     memcpy(cur,pre,sizeof(pre));
110     //for(int i=1;i<=n;i++)
111     //cout<<"cur "<<cur[i]<<endl;
112     int u=s;
113     path[u]=-1;
114     int ans=0;
115     while(dep[s]<n)//迭代寻找增广路,n为节点数
116     {
117         if(u==t)
118         {
119             int f=INF;
120             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
121                 f=min(f,edge[i].cap-edge[i].flow);
122             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
123             {
124                 edge[i].flow+=f;
125                 edge[i^1].flow-=f;
126             }
127             ans+=f;
128             u=s;
129             continue;
130         }
131         bool flag=false;
132         int v;
133         for(int i=cur[u];i!=-1;i=edge[i].next)
134         {
135             v=edge[i].v;
136             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
137             {
138                 cur[u]=path[v]=i;//当前弧优化
139                 flag=true;
140                 break;
141             }
142         }
143         if(flag)
144         {
145             u=v;
146             continue;
147         }
148         int x=n;
149         if(!(--gap[dep[u]]))return ans;//gap优化
150         for(int i=pre[u];i!=-1;i=edge[i].next)
151         {
152             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
153             {
154                 x=dep[edge[i].v];
155                 cur[u]=i;//常数优化
156             }
157         }
158         dep[u]=x+1;
159         gap[dep[u]]++;
160         if(u!=s)//当前点没有增广路则后退一个点
161         u=edge[path[u]^1].v;
162      }
163      return ans;
164 }
165 struct Bian{
166     int x,y,v;
167 }B[MAXN];
168 
169 int main(){
170 
171     std::ios::sync_with_stdio(false);
172     int T;
173     cin>>T;
174     while(T--){
175         cin>>n;
176         for(int i=0;i<=n;i++){
177             dis[i]=INF;
178             vis[i]=0;
179         }
180         for(int i=0;i<=n;i++){
181             ve[i].clear();
182         }
183         int a,b,c;
184         int j;
185         int co=0;
186         while(cin>>B[co].x>>B[co].y>>B[co].v){
187             if(!B[co].x&&!B[co].y&&!B[co].v){
188                 break;
189             }
190             ve[B[co].x].push_back(make_pair(B[co].y,B[co].v));
191             ve[B[co].y].push_back(make_pair(B[co].x,B[co].v));
192             co++;
193         }
194         Dijstra();
195         isap_init();
196         if(dis[n]==INF||n==1){
197             cout<<0<<endl;
198             continue;
199         }
200         for(int i=0;i<co;i++){///判断是不是最短路上的边
201             if(dis[B[i].x]-dis[B[i].y]==B[i].v){
202                 add(B[i].y,B[i].x,1);
203             }
204             else if(dis[B[i].y]-dis[B[i].x]==B[i].v){
205                 add(B[i].x,B[i].y,1);
206             }
207         }
208         int s=1,t=n;
209         int ans=isap(s,t);
210         cout<<ans<<endl;
211     }
212 
213 }
View Code
原文地址:https://www.cnblogs.com/Fighting-sh/p/9901752.html