最短路记录路径,同一时候求出最短的路径上最少要有多少条边,
然后用在最短路上的边又一次构图后求最小割.
Total Submission(s): 1584 Accepted Submission(s): 388
Unfortunately, Dumb Zhang masters the art of becoming invisible(奇门遁甲) and tricks devices of this tomb, he can cut off the connections between chambers by using them. Dumb Zhang wanders how many channels at least he has to cut to stop Innocent Wu. And Innocent Wu wants to know after how many channels at most Dumb Zhang cut off Innocent Wu still has the chance to catch Dumb Zhang.
For each case,the first line must includes two integers, N(<=2000), M(<=60000). N is the total number of the chambers, M is the total number of the channels.
In the following M lines, every line must includes three numbers, and use ai、bi、li as channel i connecting chamber ai and bi(1<=ai,bi<=n), it costs li(0<li<=100) minute to pass channel i.
The entrance of the tomb is at the chamber one, the end of tomb is at the chamber N.
/* *********************************************** 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; }