HDU 5889 最短路加网络流
http://acm.hdu.edu.cn/showproblem.php?pid=5889
题意: 一个无向图,每条边距离为1,从N走到1,的最短路。。然后每个路有个价值,求一下最小割
思路:裸题。。手残BFS总是写错,后来换成SPFA枚举一下就好了。。注意!!!新图建单向边来跑最短路。
代码:
#include <iostream>
#include <vector>
#include <stdio.h>
#include <queue>
#include <cstring>
#include <math.h>
using namespace std;
const int MAXN=1100;
int maze[MAXN][MAXN];
int Zdis[MAXN];
int vis[MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
const int INF=1e9+7;
struct Edge{
int v;
int cost;
Edge(int _v=0,int _cost=0):v(_v),cost(_cost) {}
};
struct T{
int x,y,z;
T(int _x=0,int _y=0,int _z=0):x(_x),y(_y),z(_z) {}
};
int tmp[MAXN];
vector<Edge>E[MAXN];
vector<T> Z;
void addedge(int u,int v,int w){
E[u].push_back(Edge(v,w));
}
void Add(int u,int v,int w){
Z.push_back(T(u,v,w));
}
int cnt[MAXN];//每个点的入队列次数
int dist[MAXN];
int n,m;
bool SPFA(int start,int n)
{
memset(vis,false,sizeof(vis));
for(int i=1; i<=n; i++)dist[i]=INF;
vis[start]=true;
dist[start]=0;
queue<int>que;
while(!que.empty())que.pop();
que.push(start);
memset(cnt,0,sizeof(cnt));
cnt[start]=1;
while(!que.empty()){
int u=que.front();
que.pop();
vis[u]=false;
for(int i=0; i<E[u].size(); i++){
int v=E[u][i].v;
if(dist[v]>dist[u]+E[u][i].cost){
dist[v]=dist[u]+E[u][i].cost;
if(!vis[v]){
vis[v]=true;
que.push(v);
if(++cnt[v]>n)return false; //cnt[i]为入队列次数,用来判定是否存在负环回路
}
}
}
}
return true;
}
void init(){
for(int i=0;i<=n;i++) E[i].clear();
Z.clear();
memset(maze,0,sizeof(maze));
}
int sap(int start,int end,int nodenum){
memset(cur,0,sizeof(cur));
memset(dis,0,sizeof(dis));
memset(gap,0,sizeof(gap));
int u=pre[start]=start,maxflow=0,aug=-1;
gap[0]=nodenum;
while(dis[start]<nodenum){
loop:
for(int v=cur[u]; v<nodenum; v++)
if(maze[u][v] && dis[u]==dis[v]+1){
if(aug==-1 || aug>maze[u][v])aug=maze[u][v];
pre[v]=u;
u=cur[u]=v;
if(v==end){
maxflow+=aug;
for(u=pre[u]; v!=start; v=u,u=pre[u]){
maze[u][v]-=aug;
maze[v][u]+=aug;
}
aug=-1;
}
goto loop;
}
int mindis=nodenum-1;
for(int v=0; v<nodenum; v++)
if(maze[u][v]&&mindis>dis[v]){
cur[u]=v;
mindis=dis[v];
}
if((--gap[dis[u]])==0)break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return maxflow;
}
int main()
{
int t;
cin>>t;
while(t--){
scanf("%d%d",&n,&m);
int a,b,c;
init();
for(int i=0;i<m;i++){
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,1);
addedge(b,a,1);
Add(a,b,c);
Add(b,a,c);
}
if(!SPFA(1,n)){
printf("0\n");
continue;
}
for(int i=0;i<=n;i++) tmp[i]=dist[i];
SPFA(n,n);
for (int i=0;i<Z.size();i++){
if (dist[Z[i].x]+tmp[Z[i].y]+1==dist[1]) {
maze[Z[i].x-1][Z[i].y-1]+=Z[i].z;
}
}
int ans=sap(n-1,0,n);
printf("%d\n",ans);
}
return 0;
}