题目大题:
求最多拆几条边图的1 -> n的最小距离不会变
求最少拆几条边图的1 -> n的最小距离会变
最短路 + 网络流的问题
求出最短路径图(包含所有最短路径的图) 之后用m - (拥有最少边数的最短路径) 得到一个解
之后将最短路径图中的边重新建图(流量为1)求最大流
感觉写的比较麻烦,时间也正好卡着过的。
#include<queue> #include<cstdio> #include<vector> #include<cstring> #include<algorithm> using namespace std; const int maxn = 2005; const int INF = 2000000000; struct W{ int u,v,dist; W(int u,int v,int dist):u(u),v(v),dist(dist){}; }; struct Edge{ int to,dist; Edge(int to = 0,int dist = 0):to(to),dist(dist){}; }; struct State{ int pos,dist,num; State(int pos,int dist = 0,int num = 0):pos(pos),dist(dist),num(num){}; friend bool operator < (State p,State q){ if(p.dist != q.dist) return p.dist > q.dist; else return p.num > q.num; } }; vector<W>edge; //------------------------BFS最短路------------------------------------------ vector<Edge>G[maxn]; int n,m,vis[maxn]; int dist[maxn]; int min_dist,min_num; int ans1,ans2; void bfs(){ min_dist = -1; min_num = -1; priority_queue<State>q; memset(dist,-1,sizeof(dist)); q.push(State(1,0,0)); while(!q.empty()){ State now = q.top(); q.pop(); if(vis[now.pos]) continue; dist[now.pos] = now.dist; if(now.pos == n){ min_dist = now.dist; min_num = now.num; } vis[now.pos] = 1; for(int i = 0; i < G[now.pos].size(); i++){ int to = G[now.pos][i].to; int dist = G[now.pos][i].dist; q.push(State(to,now.dist + dist,now.num + 1)); } } } //----------------------------最大流-------------------------------------- struct W_Edge{ int from,to,flow,cap; W_Edge(int from,int to,int flow,int cap):from(from),to(to),flow(flow),cap(cap){}; }; struct EdmondsKarp{; vector<W_Edge>w_edges; vector<int>w_G[maxn]; int n,m; int a[maxn]; //起点到i的可改进量 int p[maxn]; void init(){ w_edges.clear(); for(int i = 0; i < maxn; i++) w_G[i].clear(); } void add(int u,int v,int cap){ w_edges.push_back(W_Edge(u,v,0,cap)); w_edges.push_back(W_Edge(v,u,0,0)); int m = w_edges.size(); w_G[u].push_back(m - 2); w_G[v].push_back(m - 1); } int Maxflow(int s,int t){ int flow = 0; for(;;){ memset(a,0,sizeof(a)); queue<int>Q; Q.push(s); a[s] = INF; while(!Q.empty()){ int x = Q.front(); Q.pop(); //printf("%d\n",x); for(int i = 0; i < w_G[x].size(); i++){ W_Edge & e = w_edges[w_G[x][i]]; if(!a[e.to] && e.cap > e.flow){ p[e.to] = w_G[x][i]; a[e.to] = min(a[x],e.cap - e.flow); Q.push(e.to); } } if(a[t]) break; } if(!a[t]) break; for(int u = t; u != s; u = w_edges[p[u]].from){ w_edges[p[u]].flow += a[t]; w_edges[p[u] ^ 1].flow -= a[t]; } flow += a[t]; } return flow; } }; EdmondsKarp edm; //----------------------------找在最短路径里的边-------------------------- void Find(){ edm.init(); int Size = edge.size(); for(int i = 0; i < Size; i++){ int d = dist[edge[i].u] - dist[edge[i].v]; if(d == edge[i].dist){ edm.add(edge[i].v,edge[i].u,1); //printf("%d -> %d\n",edge[i].v,edge[i].u); } else if(- d == edge[i].dist){ edm.add(edge[i].u,edge[i].v,1); //printf("%d -> %d\n",edge[i].u,edge[i].v); } } } //----------------------------main---------------------------------------- int main(){ while(scanf("%d%d",&n,&m) != EOF){ for(int i = 1; i <= n; i++) G[i].clear(); memset(vis,0,sizeof(vis)); edge.clear(); for(int i = 0; i < m; i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); G[x].push_back(Edge(y,z)); G[y].push_back(Edge(x,z)); edge.push_back(W(x,y,z)); } bfs(); Find(); printf("%d %d\n",edm.Maxflow(1,n),m - min_num); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
时间: 2024-10-10 23:48:49