War(最短路+最大流)
Posted fighting-sh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.
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 ”.
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 }
以上是关于War(最短路+最大流)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 5294 Tricks Device (最大流+最短路)
bzoj 3931 [CQOI2015]网络吞吐量(最短路,最大流)