zoj 1760 floyd构图+Dinic最大流
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760
#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)); } }
不能用dijkstra,因为dijkstra对每个节点只访问一次。只管最小不管路径。