zoj 1760 floyd构图+Dinic最大流
2013-08-19 16:38
253 查看
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760
View Code
不能用dijkstra,因为dijkstra对每个节点只访问一次。只管最小不管路径。
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstring> #include <queue> #include <vector> #define maxn 105 #define maxe 100000 using namespace std; const int INF = 0x3f3f3f; struct Edge{ int u,v,flow,cap; int next; Edge(int u=0,int v=0,int flow=0,int cap=0,int next=0): u(u),v(v),flow(flow),cap(cap),next(next) { } }; struct Dinic{ int s,t; int d[maxn]; int cur[maxn]; bool vis[maxn]; Edge edges[maxe]; int head[maxn],cnt; void init(){ memset(head,-1,sizeof(head)); cnt = 0; } void addedge(int u,int v,int cap){ edges[cnt] = Edge(u,v,0,cap,head[u]); head[u] = cnt++; edges[cnt] = Edge(v,u,0,0,head[v]); head[v] = cnt++; } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int> Q; Q.push(s); vis[s] = true; d[s] = 0; while(!Q.empty()){ int u = Q.front(); Q.pop(); for(int i=head[u];i!=-1;i=edges[i].next){ Edge& e = edges[i]; if(!vis[e.v] && e.cap > e.flow){ vis[e.v] = true; d[e.v] = d[e.u] + 1; Q.push(e.v); } } } return vis[t]; } int dfs(int u,int res){ if(u == t || res == 0) return res; //res 残流大小; int flow = 0,f; for(int& i=cur[u];i!=-1;i=edges[i].next){ //由于dfs没有记录点是否访问过,有cur[u]是为了第二次等以后访问u时候不用重复访问一条边。 Edge& e = edges[i]; if(d[e.v] == d[e.u] + 1 && (f = dfs(e.v,min(res,e.cap-e.flow))) > 0){ e.flow += f; edges[i^1].flow -= f; flow += f; res -= f; if(res == 0) break; } } return flow; } int MaxFlow(int s_,int t_){ s = s_; t = t_; int flow = 0; while(bfs()){ for(int i=0;i<=maxn;i++) cur[i] = head[i]; //如何t不是编号最大的点,则需要改变这句。 flow += dfs(s,INF); } return flow; } }solver; int dp[maxn][maxn]; int a[maxn][maxn]; int main() { //freopen("E:\\acm\\input.txt","r",stdin); int N,s,t; while(cin>>N){ solver.init(); for(int i=0;i<N;i++) for(int j=0;j<N;j++){ scanf("%d",&a[i][j]); if(i == j) a[i][j] = 0; if(a[i][j] == -1) dp[i][j] = INF; else dp[i][j] = a[i][j]; } scanf("%d %d",&s,&t); if(s == t){ printf("inf\n"); continue; } for(int k=0;k<N;k++) for(int i=0;i<N;i++){ if(dp[i][k] >= INF) continue; for(int j=0;j<N;j++){ if(dp[k][j] >= INF) continue; dp[i][j] = min(dp[i][j],dp[i][k]+dp[k][j]); } } for(int i=0;i<N;i++) for(int j=0;j<N;j++){ if(a[i][j] == -1 || i == j) continue; if(dp[s][i]+a[i][j]+dp[j][t] == dp[s][t] ) solver.addedge(i,j,1); } printf("%d\n",solver.MaxFlow(s,t)); } }
View Code
不能用dijkstra,因为dijkstra对每个节点只访问一次。只管最小不管路径。
相关文章推荐
- 【有源汇点上下界最大流】[ZOJ3229]Shoot the Bullet
- zoj 1074 最大子段和的推广 dp
- ZOJ Problem Set–1760 Doubles
- ZOJ3305 Get Sauce(最大流)
- [ACM_水题] ZOJ 3712 [Hard to Play 300 100 50 最大最小]
- ZOJ 3762 Pan's Labyrinth (点集中的最大点-线距&技巧性枚举)
- zoj 2314 Reactor Cooling--无源汇有上下界最大流--递归sap
- zoj 1516 Uncle Tom's Inherited Land 最大独立边集合(最大匹配)
- ZOJ-1654 Place the Robots 拆行拆列构图+二分匹配 Or 最大独立点集+TLE
- zoj 1654(最大二分匹配)
- POJ 1459 Power Network / HIT 1228 Power Network / UVAlive 2760 Power Network / ZOJ 1734 Power Network / FZU 1161 (网络流,最大流)
- ZOJ 3760 Treasure Hunting(最大流)
- ZOJ 3229 Shoot the Bullet 有源汇上下界最大流
- ZOJ 1654 Place the Robots(放置机器人)------最大独立集
- ZOJ 1074 最大子矩阵和问题
- ZOJ 1760 多少个两倍数
- zoj3953 Intervals 最大不重叠区间加强版 zoj排名第一~
- ZOJ 2760 How Many Shortest Path 最短路+最大流
- zoj 2532 Internship(最大流求割边)
- zoj 3135 Party of 8g 最大点权独立集