标签:
最短路记录路径,同时求出最短的路径上最少要有多少条边,
然后用在最短路上的边重新构图后求最小割.
8 9 1 2 2 2 3 2 2 4 1 3 5 3 4 5 4 5 8 1 1 6 2 6 7 5 7 8 1
2 6
/* ***********************************************
Author :CKboss
Created Time :2015年07月24日 星期五 10时07分09秒
File Name :HDOJ5294.cpp
************************************************ */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef pair<int,int> pII;
const int INF=0x3f3f3f3f;
const int maxn=2200;
int n,m;
/*************EDGE********************/
struct Edge
{
int to,next,cost,cap,flow;
}edge[maxn*60],edge2[maxn*60];
int Adj[maxn],Size;
int Adj2[maxn],Size2;
void Add_Edge(int u,int v,int c)
{
edge[Size].to=v;
edge[Size].next=Adj[u];
edge[Size].cost=c;
Adj[u]=Size++;
}
/********spfa************/
int dist[maxn];
bool inQ[maxn];
vector<int> Pre[maxn];
int spfa(Edge* edge,int* Adj)
{
memset(dist,63,sizeof(dist));
memset(inQ,false,sizeof(inQ));
dist[1]=0;
queue<int> q;
inQ[1]=true;q.push(1);
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=Adj[u];~i;i=edge[i].next)
{
int v=edge[i].to;
if(dist[v]>dist[u]+edge[i].cost)
{
Pre[v].clear();
Pre[v].push_back(u);
dist[v]=dist[u]+edge[i].cost;
if(!inQ[v])
{
inQ[v]=true;
q.push(v);
}
}
else if(dist[v]==dist[u]+edge[i].cost)
{
Pre[v].push_back(u);
}
}
inQ[u]=false;
}
return dist[n];
}
/********************rebuild************************/
void Add_Edge2(int u,int v,int w,int rw=0)
{
edge2[Size2].cost=1;
edge2[Size2].to=v; edge2[Size2].cap=w; edge2[Size2].next=Adj2[u];
edge2[Size2].flow=0; Adj2[u]=Size2++;
edge2[Size2].cost=1;
edge2[Size2].to=u; edge2[Size2].cap=w; edge2[Size2].next=Adj2[v];
edge2[Size2].flow=0; Adj2[v]=Size2++;
}
bool used[maxn];
int edges;
void rebuild()
{
memset(used,false,sizeof(used));
queue<int> q;
q.push(n); used[n]=true;
edges=0;
while(!q.empty())
{
int v=q.front(); q.pop();
for(int i=0,sz=Pre[v].size();i<sz;i++)
{
int u=Pre[v][i];
/// u--->v
//cout<<u<<" ---> "<<v<<endl;
edges++;
Add_Edge2(u,v,1);
if(used[u]==false)
{
used[u]=true; q.push(u);
}
}
}
}
/************************max_flow*******************************/
int gap[maxn],dep[maxn],pre[maxn],cur[maxn];
int sap(int start,int end,int N,Edge* edge=edge2)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,Adj2,sizeof(Adj2));
int u=start;
pre[u]=-1; gap[0]=N;
int ans=0;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u];~i;i=pre[edge[i^1].to])
{
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[u];~i;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];~i;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v; continue;
}
int Min=N;
for(int i=Adj2[u];~i;i=edge[i].next)
{
if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start) u=edge[pre[u]^1].to;
}
return ans;
}
void init()
{
memset(Adj,-1,sizeof(Adj)); Size=0;
memset(Adj2,-1,sizeof(Adj2)); Size2=0;
for(int i=1;i<=n;i++) Pre[i].clear();
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(int i=0,u,v,c;i<m;i++)
{
scanf("%d%d%d",&u,&v,&c);
Add_Edge(u,v,c); Add_Edge(v,u,c);
}
spfa(edge,Adj);
rebuild();
int max_flow=sap(1,n,n);
int min_short_path=spfa(edge2,Adj2);
printf("%d %d\n",max_flow,m-min_short_path);
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
HDOJ 5294 Tricks Device 最短路(记录路径)+最小割
标签:
原文地址:http://blog.csdn.net/ck_boss/article/details/47041537