题目:
给一个图,起点1,终点n
必须走最短路才能从起点到终点。问至少删除几条边使得无法从起点到终点。
且删除最多几条边,还可以从起点到终点。
分析:做最短路,所有满足dist[u] = dist[v] + w(v,u)的边都是最短路的边,
对这样的边,重新建图。新图加入e(u,v),边权为1
t到s作最短路d,就是最少需要的边数能够到达边数,总边数-d就是最多能删除的边
对新图t,s作网络流,求最小割,就是最少需要删除的边数。
#include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<vector> #include<queue> #include<set> using namespace std; #define maxn 3000 #define pl pair<int,int> #define V first #define D second vector<pl>head[maxn]; struct comp{ bool operator()(pl a, pl b){ if(a.D == b.D) return a.V < b.V; return a.D < b.D; } }; int dist[maxn]; void work(int S,int E){ set<pl,comp> haha; memset(dist,0x3f,sizeof(dist)); dist[S] = 0; pl a,b; a.V = S; a.D = 0; haha.insert(a); int v,d,w; while(haha.size() > 0){ do{ a = *haha.begin(); haha.erase(haha.begin()); }while(dist[a.V] < a.D && haha.size() > 0); for(int i = 0;i < head[a.V].size(); i++){ v = head[a.V][i].V; d = head[a.V][i].D; if(dist[v] > dist[a.V] + d){ dist[v] = dist[a.V] + d; b.V = v; b.D = dist[v]; haha.insert(b); } } } } int cnt = 0; int head1[3000]; struct Edge{ int u,next,v,d; }; Edge edge[1000000]; void addedge(int u,int v,int d){ edge[cnt].u = u; edge[cnt].v = v; edge[cnt].d = d; edge[cnt].next = head1[u]; head1[u] = cnt++; edge[cnt].v = u; edge[cnt].u = v; edge[cnt].d = 0; edge[cnt].next = head1[v]; head1[v] = cnt++; } int floor[3000]; int bfs(int s,int t){ queue<int> q; q.push(s); memset(floor,0,sizeof(floor)); floor[s] = 1; while(!q.empty()){ int u = q.front(); q.pop(); for(int j = head1[u]; j != -1; j=edge[j].next){ int v = edge[j].v; if(floor[v] == 0){ floor[v] = floor[u]+1; q.push(v); } } } return floor[t]-floor[s]; } bool BFS(int s,int e){//分层 queue<int>Q; memset (floor, 0, sizeof(floor)); while(Q.size() > 0) Q.pop(); Q.push(s); floor[s] = 1; while(!Q.empty()){ int u = Q.front(); Q.pop(); for(int i=head1[u];i!=-1;i=edge[i].next){ int v = edge[i].v; if(floor[v]==0&&edge[i].d > 0){ Q.push(v); floor[v] = floor[u] + 1; } } } return floor[e] != 0; } int DFS(int u, int e,int in){//dinic if(u == e) return in; int res = in,flowout; for(int i = head1[u];i != -1;i = edge[i].next) { int v = edge[i].v; if(floor[v] != floor[u] + 1 || edge[i].d == 0 ) continue; flowout = DFS(v, e,min(res,edge[i].d)); edge[i].d -= flowout; edge[i^1].d += flowout; res -= flowout; } return in - res; } int network(int s,int e){ //s 源 int max_flow = 0,flow; while(BFS(s,e)){ while(flow = DFS(s,e,100000000)) max_flow += flow; } return max_flow; } int main(){ int n,m; while(scanf("%d%d",&n,&m)!=EOF){ int u,v,d; for(int i = 1;i <= n;i++) head[i].clear(); for(int i = 0;i < m; i++){ scanf("%d%d%d",&u,&v,&d); pl a(v,d); head[u].push_back(a); pl b(u,d); head[v].push_back(b); } work(1,n); memset(head1,-1,sizeof(head1)); cnt = 0; for(int i = 1;i < n; i++){ for(int j = 0;j < head[i].size(); j++){ int u = head[i][j].V; int d = head[i][j].D; if(dist[u] == dist[i]+d) addedge(u,i,1); } } int ans1 = bfs(n,1); int ans2 = network(n,1); cout<<ans2<<" "<<m-ans1<<endl; } return 0; }