首先要求出1到N的所有最短路,第一问等于至少去掉多少条边使所有最短路断掉,第二问就是M-最短路中边数最短的路径边数。
求最短路用Dijkstra即可,维护每个节点的父节点(用vector)。然后dfs对于每条边在网络流中建一条流量为1的边,最后跑一个最大流(即最小割)即可。
注意:
1.向函数里传对象时要加&(引用)
2.dfs时要用记忆化,保证每条边走一次,否则会重复添加网络流中的边!!
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; #define INF 100000000 #define maxn 2010 struct Edge{ int from,to,cap,flow; Edge(int f,int t,int c,int fl){ from=f; to=t; cap=c; flow=fl; }; }; struct Dinic{ int n,m,s,t; vector<Edge> edges; vector<int> G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; void Addedge(int from,int to,int cap){ edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool bfs(){ memset(vis,0,sizeof(vis)); queue<int> Q; Q.push(s); d[s]=0; vis[s]=1; while(!Q.empty()){ int x=Q.front();Q.pop(); for(int i=0;i<G[x].size();i++){ Edge& e= edges[G[x][i]]; if(!vis[e.to]&&e.cap>e.flow){ vis[e.to]=1; d[e.to]=d[x]+1; Q.push(e.to); } } } return vis[t]; } int dfs(int x,int a){ if(x==t||a==0) return a; int flow=0,f; for(int& i=cur[x];i<G[x].size();i++){ Edge&e = edges[G[x][i]]; if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){ e.flow+=f; edges[G[x][i]^1].flow-=f; flow+=f; a-=f; if(a==0) break; } } return flow; } int maxflow(int s,int t){ this->s=s;this->t=t; int flow=0; while(bfs()){ memset(cur,0,sizeof(cur)); flow+=dfs(s,INF); } return flow; } }; struct Edge2{ int from,to,dist; Edge2(int f,int t,int d){ from=f; to=t; dist=d; } }; struct HeapNode{ int d,u; bool operator < (const HeapNode& rhs) const{ return d>rhs.d; } HeapNode(int dd,int uu){ d=dd; u=uu; } }; vector <int> fa[maxn]; struct Dijkstra{ int n,m; vector<Edge2> edges; vector<int> G[maxn]; bool done[maxn]; int d[maxn]; void init(int n){ this->n=n; for(int i=0;i<=n;i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int dist){ edges.push_back(Edge2(from,to,dist)); m=edges.size(); G[from].push_back(m-1); } void dijkstra(int s){ priority_queue<HeapNode> Q; for(int i=0;i<=n;i++) d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); Q.push(HeapNode(0,s)); while(!Q.empty()){ HeapNode x=Q.top();Q.pop(); int u=x.u; if(done[u]) continue; done[u]=1; for(int i=0;i<G[u].size();i++){ Edge2&e=edges[G[u][i]]; if(d[e.to]>d[u]+e.dist){ d[e.to]=d[u]+e.dist; fa[e.to].clear(); fa[e.to].push_back(u); Q.push(HeapNode(d[e.to],e.to)); } else if(d[e.to]==d[u]+e.dist){ fa[e.to].push_back(u); } } } } }; int num[maxn]; int solve(int n,Dinic &D){ if(num[n]!=INF) return num[n]; if(n==1) return num[n]=0; for(int i=0;i<fa[n].size();i++){ D.Addedge(fa[n][i],n,1); D.Addedge(n,fa[n][i],1); num[n]=min(num[n],solve(fa[n][i],D)+1); } return num[n]; } int main(){ int N,M; while(~scanf("%d%d",&N,&M)){ Dinic dinic; Dijkstra dij; dij.init(N); for(int i=0;i<=N;i++){ fa[i].clear(); num[i]=INF; } for(int i=0;i<M;i++){ int s,t,d; scanf("%d%d%d",&s,&t,&d); dij.AddEdge(s,t,d); dij.AddEdge(t,s,d); } dij.dijkstra(1); int res2=solve(N,dinic); int res1=dinic.maxflow(1,N); printf("%d %d\n",res1,M-res2); } return 0; } /* 4 4 1 2 1 2 4 2 1 3 2 3 4 1 */