最短路记录路径,同时求出最短的路径上最少要有多少条边,
然后用在最短路上的边重新构图后求最小割.
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; }