您的位置:首页 > 其它

zoj 1760 floyd构图+Dinic最大流

2013-08-19 16:38 253 查看
题目链接: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));
}
}


View Code
不能用dijkstra,因为dijkstra对每个节点只访问一次。只管最小不管路径。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: